---
description: https://viblo.asia/p/laravel-tim-hieu-ve-cache-bJzKmk7El9N
---

# Laravel: tìm hiểu về cache

## Laravel: tìm hiểu về cache

Bài đăng này đã không được cập nhật trong 4 năm

## Configuration <a href="#configuration-0" id="configuration-0"></a>

\


Laravel cung cấp một API thống nhất cho các caching backend khác nhau. Cấu hình cho cache được đặt trong file `config/cache.php`. Trong file này bạn có thể chỉ định cache driver nào bạn muốn sử dụng mặc định trong ứng dụng của bạn. Laravel hỗ trợ các hệ thông cache phổ biến như [Memcached](https://memcached.org/) và [Redis](https://redis.io/). File cấu hình cache cũng chứa các tuỳ chọn khác nhau, đều được ghi chú đầy đủ bên trong file, do đó hãy nhớ đọc qua các tùy chọn này. Mặc định, Laravel được cấu hình để sửa dụng cache driver bằng `file` , nơi mà các serialized được lưu, các đối tương cached trong filesystem. Với các ứng dụng lớn hơn, bạn nên sử dụng các driver mạnh mẽ hơn như Memcached hay Redis. Bạn thậm chí có thẻ cấu hình để sử dụng nhiều cấu hình cache cho cùng một driver.

\


#### Driver Prerequisites <a href="#driver-prerequisites-1" id="driver-prerequisites-1"></a>

**Database**

Khi sử dụng cache driver `database`, bạn sẽ cần thiết lập một bảng để lưu trữ các cache items. Bạn sẽ thấy một ví dụ về khai báo `Schema` cho bảng dưới đây:

```
Schema::create('cache', function ($table) {
    $table->string('key')->unique();
    $table->text('value');
    $table->integer('expiration');
});
```

**Memcached** Sử dụng Memcached driver yêu cầu [Memcached PECL package](https://pecl.php.net/package/memcached) phải được cài đặt. Bạn có thể list tất cả Memcached servers của bạn trong file cấu hình `config/cache.php`:

```
'memcached' => [
    [
        'host' => '127.0.0.1',
        'port' => 11211,
        'weight' => 100
    ],
],
```

Bạn cũng có thể thiết lập tùy chọn `host` tới một đường dẫn UNIX socket. Nếu làm thế này thì `port` cần được set về `0`:

```
'memcached' => [
    [
        'host' => '/var/run/memcached/memcached.sock',
        'port' => 0,
        'weight' => 100
    ],
],
```

**Redis** Trước khi sử dụng Redis cache với Laravel, bạn cần phải cài đặt`predis/predis` package (\~1.0) qua Composer hoặc cài đặt PhpRedis PHP extension qua PECL.

Thông tin thêm chi tiết về cấu hình cho Redis, hãy tham khảo [Laravel documentation page](https://laravel.com/docs/5.4/redis#configuration).

\


## Cache Usage <a href="#cache-usage-2" id="cache-usage-2"></a>

\


#### Obtaining A Cache Instance <a href="#obtaining-a-cache-instance-3" id="obtaining-a-cache-instance-3"></a>

`Illuminate\Contracts\Cache\Factory` và `Illuminate\Contracts\Cache\Repository` [contracts](https://laravel.com/docs/5.4/contracts) cung cấp truy xuất tới Laravel's cache services. `Factory` contract cung cấp truy cập tới tất cả các cache drivers được khai báo cho ứng dụng của bạn. `Repository` contract thường triển khai của cache driver mặc định cho ứng dụng mà bạn chỉ định trong file cấu hình `cache`. Tuy nhiên, bạn cũng có thể sử dụng `Cache` facade, đó là những gì mà chúng ta sẽ sử dụng trong bài này. `Cache` facade cung cấp cách truy cập thuận tiện và ngắn gọn tới các implement của các Laravel contracts:

```
<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
    /**
     * Show a list of all users of the application.
     *
     * @return Response
     */
    public function index()
    {
        $value = Cache::get('key');

        //
    }
}
```

**Accessing Multiple Cache Stores** Sử dụng `Cache` facade, bạn có thể truy xuất tới nhiều cache store thông quan phương thức `store`. Giá trị khoá truyền vào phương thức `store` cần ứng với một trong những store được liệt kê trong mảng cấu hình `stores` trong file `cache` của bạn:

```
$value = Cache::store('file')->get('foo');

Cache::store('redis')->put('bar', 'baz', 10);
```

\


#### Retrieving Items From The Cache <a href="#retrieving-items-from-the-cache-4" id="retrieving-items-from-the-cache-4"></a>

Phương thức `get` trong `Cache` facade được sử dụng để lấy các items trong cache. Nếu như item không tồn tại trong cache, giá trị `null` sẽ được trả về. Nếu muốn, bạn có thể truyền vào tham số thứ hai để phương thức `get` chỉ định giá trị mặc định nếu như item không tồn tại:

```
$value = Cache::get('key');

$value = Cache::get('key', 'default');
```

Bạn thậm chí có thể truyền vào một `Closure` như một giá trị mặc định. Kết quả của `Closure` sẽ được trả về nếu item cần lấy không tồn tại trong cache. Truyền vào một Closure cho phép bạn trì hoãn lại việc lấy giá trị mặc định từ trong một database hay từ một dịch vụ bên ngoài:

```
$value = Cache::get('key', function () {
    return DB::table(...)->get();
});
```

**Checking For Item Existence** Phương thức `has` có thể được sử dụng để kiểm tra xem một item có tồn tại trong cache hay không:

```
if (Cache::has('key')) {
    //
}
```

**Incrementing / Decrementing Values** Phương thức `increment` và `decrement` có thể được sử dụng để điều chỉnh giá trị của các items số nguyên nằm trong cache. Cả hai hàm này có tuỳ chọn cho phép tham số thứ hai chỉ định giá trị tăng giảm bao nhiêu cho cache item:

```
Cache::increment('key');
Cache::increment('key', $amount);
Cache::decrement('key');
Cache::decrement('key', $amount);
```

**Retrieve & Store** Đôi khi bạn muốn lấy ra một item trong cache, nhưng cũng muốn lưu giá trị mặc định cho item nếu như nó không tồn tại. Ví dụ, bạn muốn lấy tất cả users nằm trong cache hoặc, nếu chúng không tồn tại, thì sẽ lấy từ database và thêm vào trong cache. Bạn có thể thực hiện việc này bằng cách sử dụng phương thức `Cache::remember`:

```
$value = Cache::remember('users', $minutes, function () {
    return DB::table('users')->get();
});
```

Nếu item không tồn tại trong cache, thì `Closure` truyền vào trong phương thức `remember` sẽ được thực thi và kết quả sẽ được lưu lại vào trong cache. Bạn cũng có thể sử dụng phương thức `rememberForever` để lấy lại một item từ trong cache hoặc store nó mãi mãi:

```
$value = Cache::rememberForever('users', function() {
    return DB::table('users')->get();
});
```

**Retrieve & Delete** Nếu bạn muốn lấy ra một item trong cache và xoá đi, bạn có thể sử dụng phương thức `pull`. Giống như phương thức `get`, giá trị `null` sẽ được trả về nếu item không tồn tại trong cache từ trước đó:

```
$value = Cache::pull('key');
```

\
\### Storing Items In The Cache

Bạn có thể sử dụng phương thức `put` của `Cache` facade để lưu items vào trong cache. Khi bạn thêm một item vào trong cache, bạn sẽ cần phải chỉ rõ số phút mà giá trị sẽ được lưu:

````
Cache::put('key', 'value', $minutes);
```
Thay vì truyền vào số phút cho tới khi item bị hết hạn, bạn cũng có thể truyền vào một đối tượng PHP kiểu  ```DateTime``` để thể hiện thời gian hết hạn của item được cache:
```
$expiresAt = Carbon::now()->addMinutes(10);

Cache::put('key', 'value', $expiresAt);
````

_**Store If Not Present**_ Phương thức `add` sẽ chỉ thêm item vào cache nếu như nó chưa tồn tại. Phương thức này sẽ trả về `true` nếu item thực sự được thêm vào cache. Còn ngược lại thì hàm sẽ trả về `false`:

```
Cache::add('key', 'value', $minutes);
```

_**Storing Items Forever**_ Phương thức `forever` có thể được sử dụng để lưu một item trong cache vĩnh viễn. Những giá trị này cần phải được gỡ ra một cách thủ công bằng cách sử dụng phương thức `forget`:

```
Cache::forever('key', 'value');
```

\


#### Removing Items From The Cache <a href="#removing-items-from-the-cache-5" id="removing-items-from-the-cache-5"></a>

Bạn có thể bỏ các item từ cache bằng cách sử dụng phương thức `forget`:

```
Cache::forget('key');
```

Bạn có thể xoá toàn bộ cache bằng cách sử dụng phương thức `flush`:

```
Cache::flush();
```

\


#### The Cache Helper <a href="#the-cache-helper-6" id="the-cache-helper-6"></a>

Ngoài ra khi sử dụng `Cache` facade hoặc [cache contract](https://laravel.com/docs/5.4/contracts), bạn có thể sử dụng phương thức `cache` để nhận và lưu dữ liệu từ cache. Khi phương thức `cache` được gọi một mình, tham số string, nó sẽ trả về giá trị của key:

```
$value = cache('key');
```

Nếu bạn cung cấp một mảng của key / value và thời gian hết hạn của hàm, nó sẽ lưu giá trị vào cache với thời gian chỉ định:

```
cache(['key' => 'value'], $minutes);

cache(['key' => 'value'], Carbon::now()->addSeconds(10));
```

\


## Cache Tags <a href="#cache-tags-7" id="cache-tags-7"></a>

\


#### Storing Tagged Cache Items <a href="#storing-tagged-cache-items-8" id="storing-tagged-cache-items-8"></a>

Cache tag cho phép bạn tag các item liên quan tới nhau trong cache và sau đó flush hết các giá trị cache mà có chung một tag. Bạn có thể truy xuất vào một cache được tag bằng cách truyền vào một mảng các tên tag. Ví dụ, hãy truy cập một tagged cache và `put` giá trị vào cache:

```
Cache::tags(['people', 'artists'])->put('John', $john, $minutes);

Cache::tags(['people', 'authors'])->put('Anne', $anne, $minutes);
```

\


#### Accessing Tagged Cache Items <a href="#accessing-tagged-cache-items-9" id="accessing-tagged-cache-items-9"></a>

Để lấy một cache item được tag, truyền vào list tương tự các tag trong phương thức `tags` và sau đó gọi phương thức `get` với key bạn muốn nhận:

```
$john = Cache::tags(['people', 'artists'])->get('John');

$anne = Cache::tags(['people', 'authors'])->get('Anne');
```

\


#### Removing Tagged Cache Items <a href="#removing-tagged-cache-items-10" id="removing-tagged-cache-items-10"></a>

Bạn có thể flush tất cả các item có chung một tag hoặc danh sách các tag. Ví dụ, mã lệnh sau sẽ xoá tất cả các cache được tag với giá trị là `people`, `authors`, hoặc cả hai. Vì vậy, cả `Anne` và `John` sẽ bị xóa khỏi cache:

```
Cache::tags(['people', 'authors'])->flush();
```

Ngược lại, câu lệnh này sẽ chỉ xoá các cache có tag là `authors`, vì vậy `Anne` sẽ bị xoá, còn `John` thì không:

```
Cache::tags('authors')->flush();
```

\


## Adding Custom Cache Drivers <a href="#adding-custom-cache-drivers-11" id="adding-custom-cache-drivers-11"></a>

\


#### Writing The Driver <a href="#writing-the-driver-12" id="writing-the-driver-12"></a>

Để viết một tùy biến cache driver, đầu tiên chúng ta cần thực thi `Illuminate\Contracts\Cache\Store` [contract](https://laravel.com/docs/5.4/contracts) contract. Vì vậy, MongoDB cache thực thi sẽ giống như sau:

```
<?php

namespace App\Extensions;

use Illuminate\Contracts\Cache\Store;

class MongoStore implements Store
{
    public function get($key) {}
    public function many(array $keys);
    public function put($key, $value, $minutes) {}
    public function putMany(array $values, $minutes);
    public function increment($key, $value = 1) {}
    public function decrement($key, $value = 1) {}
    public function forever($key, $value) {}
    public function forget($key) {}
    public function flush() {}
    public function getPrefix() {}
}
```

Chúng ta chỉ cần thực thi mỗi phương thức khi sử dụng kết nối MongoDB. Một ví dụ: làm thế nào để thực thi các phương thức đó, để ý trong `Illuminate\Cache\MemcachedStore`. Khi chúng ta đã triển khai, chúng ta có thể hoàn tất đăng ký custom driver của mình.

```
Cache::extend('mongo', function ($app) {
    return Cache::repository(new MongoStore);
});
```

\


#### Registering The Driver <a href="#registering-the-driver-13" id="registering-the-driver-13"></a>

Để đăng ký custom cache driver với Laravel, chúng ta sử dụng phương thức `extend` trong `Cache` facade. Gọi `Cache::extend` có thể được thực hiện trong phương thức `boot` của `App\Providers\AppServiceProvider` mặc định, hoặc bạn có thể tạo tùy biến service provider để mở rộng - đừng quên đăng ký provider trong mảng provider `config/app.php`:

```
<?php

namespace App\Providers;

use App\Extensions\MongoStore;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;

class CacheServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Cache::extend('mongo', function ($app) {
            return Cache::repository(new MongoStore);
        });
    }

    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}
```

Tham số đầu tiên truyền vào phương thức `extend` là tên của driver. Nó tương ứng với `driver` của bạn lựa chọn trong file cấu hình `config/cache.php`. Tham số thứ hai là một Closure nên trả về một `Illuminate\Cache\Repository` instance. Closure sẽ truyền vào một `$app` instance, nó là instance của [service container](https://laravel.com/docs/5.4/container).

Khi mở rộng của bạn được đăng ký, đơn giản chỉ cần cập nhật file cấu hình `config/cache.php` `driver` giống với tên của extension của bạn.

\


## Events <a href="#events-14" id="events-14"></a>

\


Để thực thi code mỗi khi có một thao tác làm việc với cache xảy ra, bạn có thể lắng nghe các [events](https://laravel.com/docs/5.4/events) được bắn vào từ cache. Về cơ bản, bạn nên đặt những phần này vào trong `EventServiceProvider`:

```
/**
 * The event listener mappings for the application.
 *
 * @var array
 */
protected $listen = [
    'Illuminate\Cache\Events\CacheHit' => [
        'App\Listeners\LogCacheHit',
    ],

    'Illuminate\Cache\Events\CacheMissed' => [
        'App\Listeners\LogCacheMissed',
    ],

    'Illuminate\Cache\Events\KeyForgotten' => [
        'App\Listeners\LogKeyForgotten',
    ],

    'Illuminate\Cache\Events\KeyWritten' => [
        'App\Listeners\LogKeyWritten',
    ],
];
```

[Laravel](https://viblo.asia/tags/laravel)[Cache](https://viblo.asia/tags/cache)[PHP](https://viblo.asia/tags/php)
