Redisのセットアップ
-
composer require predis/predis
する -
docker-compose.yaml
にRedisを足す。yamlファイルはインテンドの高さを間違えると動かないので注意。
redis:
image: redis
ports:
- 6379:6379
-
config/database.php
のRedisクライアントをpredisに変更
//前略
'redis' => [
'client' => env('REDIS_CLIENT', 'predis'),
//後略
-
.env
でキャッシュドライバとホストを変更
CACHE_DRIVER=redis
REDIS_HOST=redis
以上でとりあえずRedisが動きます。
Cacheをコントローラで使う
とりえあずProduct::all()
の結果をキャッシュする場合を考える。
この場合、
- すでにキャッシュがあればそこからデータを取り出す
- ない場合は
Product::all()
のクエリを走らせ、結果をキャッシュする
という処理を行うこととなる。
public function frontend(){
if($products = \Cache::get('products_frontend')){
return $products;
}
$products = Product::all();
\Cache::set('products_frontend',$products,30*60);
return $products;
}
Cache::get($cache_name)
でキャッシュを呼び出せる。明快だ。Cache::set()
は第一引数がキャッシュ名、第二引数がキャッシュするデータ、第三引数がキャッシュする時間(秒単位)だ。
なおファサードからは、先頭にバックスラッシュを付けることでクラスを呼び出せる。
また上記の処理は、\Cache::remember
を使うと一行で書くことが出来る。
$products = \Cache::remember('products_frontend',30*60,fn()=>Product::all());
return $products;
イベントを使ってキャッシュを消したい!
$products
をキャッシュしたが、商品をupdateしたりcreateしたりdeleteしたりしても、getする際にはキャッシュから引っ張ってくるので情報が変わらないという問題がある。
つまり、update、create、deleteを行う場合はキャッシュを消す必要があるわけだ。
public function deleteCache(){
\Cache::forget('products_frontend');
}
とやるのも全然ありだが、ここはイベントを使って消す方法を見ていく。
まずはphp artisan make:event ProductUpdatedEvent
とphp artisan make:listener ProductUpdatedListener
を作成する。
また、EventServiceProviderに両者を登録する。
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
ProductUpdatedEvent::class=>[
ProductUpdatedListener::class
]
];
これで、ProductUpdatedEvent
のリスナとしてProductUpdatedListener
が登録される。
さて、ProductUpdatedEvent
のコードだが、今回はただ発火するだけのイベントなので、コードの大半は削っていい。
class ProductUpdatedEvent
{
use Dispatchable, InteractsWithSockets, SerializesModels;
}
そしてリスナ内に、必要な処理を書き込む。
class ProductUpdatedListener
{
public function handle( ProductUpdatedEvent $event)
{
\Cache::forget('products_frontend');
\Cache::forget('products_backend');
}
}
これで、ProductUpdatedEventがアプリのどこかで発火し次第、リスナ内のキャッシュ消去処理が実行されることになる。
最後にコントローラ内の必要箇所で、以下のコードでイベントを発火させる。
event(new ProductUpdatedEvent);