Laravel 5.7: Tìm hiểu về Cache.
Bài đăng này đã không được cập nhật trong 5 năm
Cache
Hôm nay chúng ta sẽ cùng tìm hiểu về cache trong laravel 5.7.
Configuration
Laravel cung cấp một API thống nhất cho các hệ thống cache 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. Laravel hỗ trợ sẵn các hệ thông cache phía backends phổ biến như Memcached và Redis.
File cấu hình cache cũng chứa các tuỳ chọn khác, đều được ghi chú đầy đủ bên trong, vì thế hãy nhớ đọc kĩ chỉ dẫn trong đó. Mặc định, Laravel được cấu hình để sửa dụng cache driver là file
, để lưu trữ các cache object đã được serialized trong filesystem.
Driver Prerequisites (Yêu cầu)
database
Khi sử dụng cache driver database
để lưu cache, bạn sẽ cần thiết lập một bảng để lưu trữ các cache items. Schema
như sau:
Schema::create('cache', function($table) {
$table->string('key')->unique();
$table->text('value');
$table->integer('expiration');
});
Có thể sử dụng câu lệnh Artisan php artisan cache:table
để tạo ra một migration.
Memcached
Sử dụng Memcached yêu cầu thư viện Memcached PECL.
Config mặc định sử dụng TCP_IP.
'memcached' => [
[
'host' => '127.0.0.1',
'port' => 11211,
'weight' => 100
],
],
Bạn cũng có thể thiết lập thông số host
. 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 install package Composer predis/predis
(~1.0).
Cahe Usage
Obtaining A Cache Instance
Hai contracts Illuminate\Contracts\Cache\Factory
và Illuminate\Contracts\Cache\Repository
cung cấp truy xuất tới Laravel cache services. Contract Factory
cung cấp tuy cập tới tất cả các cache drivers được khai báo cho ứng dụng. Contract Repository
về cơ bản là 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, mà bạn sẽ thấy trong suốt tài liệu này.
<?php
namespace App\Http\Controllers;
use 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 cho phép bạn có thể truy xuất tới nhiều cache store thông quan hàm store
. Giá trị khoá truyền vào hàm store
cần ứng với một trong những store danh sách các stores
của mảng cấu hình trong file cấu hình cache
:
$value = Cache::store('file')->get('foo');
Cache::store('redis')->put('bar', 'baz', 10);
Retrieving Items From The Cache
Hàm 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 để hàm 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
Function has
có thể được sử dụng để kiểm tra xem một item có tồn tại trong cache hay không như sau:
if (Cache::has('key')) {
// Key exists
}
Incrementing / Decrementing Values
Hai hàm 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 lúc 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ư 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 hàm 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 hàm 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ể kết hợp hai hàm remember
và forever
với nhau:
$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 hàm pull
. Giống như hàm get
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 hàm 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
Hàm add
sẽ chỉ thêm item vào cache nếu như nó chưa tồn tại sẵn. Hàm 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
Hàm 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 sử dụng hàm forget
:
Cache::forever('key', 'value');
Store If Not Present
Bạn có thể xoá items khỏi cache sử dụng hàm forget
trong Cache
facade:
Cache::forget('key');
Removing Items From The Cache
Bạn có thể xoá toàn bộ cache sử dụng hàm flush
:
Cache::flush();
Việc xoá toàn bộ cache không hề
tuân theo tiền tố cache nào, mà sẽ thực hiện xoá toàn bộ tất cả trong cache. Vì thế hãy thực sự cẩn trọng khi xoá một giá trị cache mà được sử dụng chung giữa các ứng dụng.
Atomic Locks
Atomic locks cho phép thao tác với các thành phần không lo lắng về các điều kiện.
if (Cache::lock('foo', 10)->get()) {
// Lock acquired for 10 seconds...
Cache::lock('foo')->release();
Method get
Phương thức get cũng được chấp thuận sau khi thực thi Atomic Locks sẽ được giải phóng
Cache::lock('foo')->get(function () {
// Lock acquired indefinitely and automatically released...
});
The Cache Helper
Ngoài việc sử dụng đồng bộ cache hoặc đồng bộ Cache facade , bạn cũng có thể sử dụng chức năng cache chung để truy xuất và lưu trữ dữ liệu qua cache. Khi hàm cache được gọi với một đối số chuỗi, nó sẽ trả về giá trị của khóa đã cho:
$value = cache('key');
Khi bạn cung cấp một mảng các cặp khóa / giá trị và thời gian hết hạn cho hàm, nó sẽ lưu các giá trị trong cache với thời gian được chỉ định.
cache(['key' => 'value'], $minutes);
cache(['key' => 'value'], now()->addSeconds(10));
Khi chức năng cache được gọi mà không có đối số, nó sẽ trả về 1 thể hiện is an instance of the Illuminate\Contracts\Cache\Factory
implementation
, cho phép bạn thực hiện cache khác
cache()->remember('users', $minutes, function () {
return DB::table('users')->get();
});
Cache Tags
Lưu ý: Cache tag không hỗ trợ khi sử dụng cache driver là
file
vàdatabase
. Thêm nữa, khi sử dụng nhiều tag với cache được lưu dưới dạng "forever", hiệu năng sẽ đạt tốt nhất ở driver có khả năng tự động xoá các danh sách đã lưu quá lâu nhưmemcached
.
Storing Tagged Cache Items
Cache tag cho phép bạn tag các item liên quan tới nhau trong cache và có thể xoá 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:
Cache::tags(['people', 'artists'])->put('John', $john, $minutes);
Cache::tags(['people', 'authors'])->put('Anne', $anne, $minutes);
Tuy nhiên, bạn không hề bị hạn chế khi sử dụng hàm put
. Bạn có thể sử dụng bất cứ hàm lưu trữ cache nào khi làm việc với tag.
Accessing Tagged Cache Items
Để lấy một cache item được tag, truyền vào danh sách tương tự các tag trong hàm tags
:
``
$john = Cache::tags(['people', 'artists'])->get('John');
$anne = Cache::tags(['people', 'authors'])->get('Anne');
``
Bạn có thể xoá 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ì thế, cả hai khoá là Anne
và John
sẽ bị xoá 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ì thế Anne
sẽ bị xoá, còn John
thì không.
Cache::tags('authors')->flush();
Adding Custom Cache Drivers
Để mở rộng Laravel với một cache driver tuỳ chọn, chúng ta sẽ sử dụng hàm extend
trong Cache
facade, để có thể thực hiện liên kết tới phần quản lý. Về cơ bản, việc này sẽ thông qua một [service provider]
Ví dụ, để đăng kí một cache driver mới là "mongo" viết như sau:
<?php
namespace App\Providers;
use Cache;
use App\Extensions\MongoStore;
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ố thứ nhất truyền vào hàm extend
là tên của driver. Cái này tương ứng với thông số driver
trong file cấu hình config/cache.php
. Tham số thứ hai là một Closure mà sẽ trả về một đối tượng kiểu Illuminate\Cache\Repository
. Closure này sẽ được truyền vào đối tượng $app
, chính là [service container].
Việc gọi tới Cache::extend
có thể được gọi trong hàm boot
của App\Providers\AppServiceProvider
được đi kèm trong một ứng dụng Laravel mới cài đặt, hoặc bạn có thể tạo service provider riêng để quản lý việc mở rộng - đừng quên việc đăng kí provider vào trong danh sách providers nằm trong file cấu hình config/app.php
.
Để tạo một cache driver riêng, trước tiên chúng ta cần phải triển khai Illuminate\Contracts\Cache\Store
contract]Do đó, việc triển khải MongoDB cache sẽ kiểu như thế này:
<?php
namespace App\Extensions;
class MongoStore implements \Illuminate\Contracts\Cache\Store
{
public function get($key) {}
public function put($key, $value, $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 triển khai cho mỗi hàm này sử dụng một connection tới MongoDB. Khi mà triển khai hoàn thiện, chúng ta sẽ hoàn thiện việc đăng kí cache driver:
Cache::extend('mongo', function($app) {
return Cache::repository(new MongoStore);
});
Khi mà việc mở rộng hoàn thiện, chỉ cần cập nhất tên giá trị driver
trong file cấu hình config/cache.php
.
Nếu bạn băn khoăn việc đặt code cho cache driver riêng ở đâu, hãy nghĩ tới việc tạo thành thư viện trên Packagist! Hoặc là, bạn có thể tạo một namespace Extensions
trong thư mục app
. Tuy nhiên, nên nhớ là Laravel không có cứng nhắc trong cấu trúc ứng dụng và bạn hoàn toàn thoải mái trong việc quản lý ứng dụng theo cách bạn muốn.
Events
Để 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 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',
],
];
Bài viết của mình đến đây là hết hẹn gặp lại các bạn ở các bài viết tiếp theo.
Tài liệu tham khảo:
All rights reserved