キャッシュ
時間のかかる結果を取っておいて速く返す「キャッシュ」の設定と使い方、タグ・ロック・フェイルオーバー・独自ドライバー・イベントを説明します。
キャッシュとは、一度作った結果を取っておき、次から速く返すしくみです。よく使うものを手元に置いておくメモのようなものです。アプリの仕事には、計算に時間がかかったり、取ってくるのに数秒かかったりするものがあります。その結果を少しのあいだ覚えておけば、同じデータをもう一度ほしがられたときに、すぐ返せます。取っておく場所には、Memcached や Redis のような、とても速いデータの置き場が使われることが多いです。
Laravel は、いろいろな置き場を、同じ書き方で使えるようにしてくれます。
設定#
キャッシュの設定ファイルは config/cache.php です。ここで、アプリ全体で使う標準のキャッシュ置き場(ストア)を決めます。Laravel は、Memcached・Redis・DynamoDB・リレーショナルデータベース(表でデータを持つふつうのデータベース)・ファイルシステムのディスクに、はじめから対応しています。ファイルに置く方式のドライバー(置き場ごとのつなぎ方)もあります。さらに、自動テスト用に、array と null というドライバーも用意されています。
設定ファイルには、ほかにも見直せる項目がいろいろあります。ふつうの設定では、database ドライバーが使われます。取っておくデータを、アプリのデータベースの中に、文字の形にして保存します。
ドライバーごとの準備#
データベース#
database ドライバーを使うときは、キャッシュを入れる表がデータベースに必要です。ふつうは、Laravel にはじめから入っている 0001_01_01_000001_create_cache_table.php というマイグレーション(データベースの表を作ったり変えたりする手順書)が作ってくれます。このマイグレーションが無いときは、make:cache-table という Artisan コマンドで作れます。
php artisan make:cache-table
php artisan migrate
Memcached#
Memcached ドライバーを使うには、Memcached PECL パッケージ(PHP の拡張部品)を入れておく必要があります。Memcached のサーバーは、config/cache.php に並べて書けます。ここには、はじめから memcached.servers の見本が入っています。
'memcached' => [
// ...
'servers' => [
[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
'port' => env('MEMCACHED_PORT', 11211),
'weight' => 100,
],
],
],
必要なら、host には UNIX ソケット(同じパソコンの中でつなぐための道すじ)のパスも書けます。その場合は、port を 0 にします。
'memcached' => [
// ...
'servers' => [
[
'host' => '/var/run/memcached/memcached.sock',
'port' => 0,
'weight' => 100
],
],
],
Redis#
Laravel で Redis のキャッシュを使う前に、PECL で PhpRedis という PHP の拡張を入れるか、Composer で predis/predis パッケージを入れる必要があります。Laravel Sail(Docker の中で Laravel を動かす道具)には、この拡張がはじめから入っています。公式のアプリの置き場(Laravel Cloud や Laravel Forge)にも、PhpRedis の拡張がはじめから入っています。
Redis の設定のくわしいことは、公式ドキュメントの Redis のページにあります。
ストレージ#
storage ドライバーを使うと、キャッシュの値を、アプリに設定したファイルのディスクのどこにでも保存できます。S3 のディスクのような、すでにあるディスクを、キーと値のキャッシュ置き場として使いたいときに便利です。
'storage' => [
'driver' => 'storage',
'disk' => env('CACHE_STORAGE_DISK'),
'path' => env('CACHE_STORAGE_PATH', 'framework/cache/data'),
],
DynamoDB#
DynamoDB ドライバーを使う前に、キャッシュを入れる DynamoDB の表を作る必要があります。ふつうの表の名前は cache です。ただし、cache 設定ファイルの stores.dynamodb.table の値に合わせた名前にしてください。表の名前は、DYNAMODB_CACHE_TABLE 環境変数でも決められます。
この表には、文字列のパーティションキー(行を見つける目印の列)も必要です。名前は、設定ファイルの stores.dynamodb.attributes.key の値と同じにします。ふつうは key という名前です。
DynamoDB は、ふつう、期限が切れたデータを自分から消してくれません。そのため、表で TTL(期限が来たら自動で消す機能)を有効にしてください。TTL の設定では、TTL の列の名前を expires_at にします。
次に、Laravel のアプリが DynamoDB と通信できるように、AWS SDK(AWS のサービスを PHP から使うための部品)を入れます。
composer require aws/aws-sdk-php
さらに、DynamoDB のキャッシュ置き場の設定に、値を入れておいてください。AWS_ACCESS_KEY_ID や AWS_SECRET_ACCESS_KEY のような値は、ふつう、アプリの .env ファイルに書きます。
'dynamodb' => [
'driver' => 'dynamodb',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
'table' => env('DYNAMODB_CACHE_TABLE', 'cache'),
'endpoint' => env('DYNAMODB_ENDPOINT'),
],
MongoDB#
MongoDB を使っているときは、公式の mongodb/laravel-mongodb パッケージが mongodb ドライバーを用意しています。mongodb という名前のデータベース接続で設定します。MongoDB には、期限の切れたキャッシュを自動で消せる TTL インデックスがあります。
MongoDB の設定のくわしいことは、MongoDB の公式ドキュメント(Cache and Locks)にあります。
| ドライバー | 説明 |
|---|---|
database |
アプリのデータベースの表に保存する。ふつうの設定 |
memcached |
Memcached に保存する。PECL パッケージが必要 |
redis |
Redis に保存する。PhpRedis か predis/predis が必要 |
dynamodb |
DynamoDB に保存する。表と AWS SDK が必要 |
file |
ファイルに保存する |
storage |
設定したファイルのディスクに保存する |
mongodb |
MongoDB に保存する。mongodb/laravel-mongodb パッケージが必要 |
array |
その場のメモリにだけ置く。自動テスト向き |
null |
何も保存しない。自動テスト向き |
failover |
失敗したら次のストアを使う。下の「フェイルオーバー」を見る |
キャッシュの使い方#
キャッシュを使う入口#
キャッシュの置き場を使うには、Cache ファサード(Cache::get() のように、クラス名と :: で機能を呼べる窓口)を使います。このページでは、ずっとこれを使います。Cache ファサードは、Laravel のキャッシュのコントラクト(約束ごと)の中身へ、短い書き方で入れる入口です。
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Cache;
class UserController extends Controller
{
/**
* Show a list of all users of the application.
*/
public function index(): array
{
$value = Cache::get('key');
return [
// ...
];
}
}
複数の置き場を使い分ける#
Cache ファサードの store を使うと、いろいろな置き場を選べます。store に渡す名前は、cache 設定ファイルの stores 配列にある名前のどれかにします。
$value = Cache::store('file')->get('foo');
Cache::store('redis')->put('bar', 'baz', 600); // 10 分
キャッシュから取り出す#
Cache ファサードの get で、キャッシュから値を取り出します。無ければ null が返ります。2つ目の引数に、無いときに返す初期値を渡せます。
$value = Cache::get('key');
$value = Cache::get('key', 'default');
初期値には、クロージャ(名前のない関数)も渡せます。値が無いときだけクロージャが動き、その結果が返ります。データベースなどから初期値を取ってくる処理を、必要になるまで後回しにできます。
$value = Cache::get('key', function () {
return DB::table(/* ... */)->get();
});
あるかどうかを調べる#
has で、値があるかを調べます。値はあっても中身が null のときは、false を返します。
if (Cache::has('key')) {
// ...
}
増やす・減らす#
increment と decrement で、キャッシュの整数の値を増やしたり減らしたりできます。2つ目の引数に、増やす(減らす)量を渡せます。
// 値が無ければ、はじめの値を入れる
Cache::add('key', 0, now()->plus(hours: 4));
// 値を増やす・減らす
Cache::increment('key');
Cache::increment('key', $amount);
Cache::decrement('key');
Cache::decrement('key', $amount);
取り出して、無ければ保存する#
キャッシュから取り出したいけれど、無ければ初期値を保存したい、ということがあります。たとえば、全ユーザーをキャッシュから取り、無ければデータベースから取ってキャッシュに入れる場合です。Cache::remember を使います。
$value = Cache::remember('users', $seconds, function () {
return DB::table('users')->get();
});
キャッシュに無いときだけ、remember に渡したクロージャが動き、その結果がキャッシュに入ります。
値をキャッシュから取れたのか、クロージャで作ったのかを知りたいときは、rememberWithWarmth を使います。キャッシュの値と、「ウォーム」だったか(キャッシュから取れたか)の真偽値が入った配列が返ります。
[$value, $warm] = Cache::rememberWithWarmth('users', $seconds, function () {
return DB::table('users')->get();
});
取り出して、無ければ期限なしで保存するには rememberForever を使います。
$value = Cache::rememberForever('users', function () {
return DB::table('users')->get();
});
古い値を返しながら作り直す(Stale While Revalidate)#
Cache::remember を使うと、キャッシュの期限が切れたとき、そのときにアクセスした人の返事が遅くなることがあります。データによっては、少し古い値を返しながら、裏で新しい値を作り直しても困りません。こうすると、値を作っているあいだに待たされる人が減ります。このやり方は「stale-while-revalidate」と呼ばれ、Cache::flexible で使えます。
flexible には、配列を渡します。1つ目の値は、キャッシュが「新鮮」な秒数、2つ目の値は、「古い」状態で返してよい秒数の終わりです。
- 1つ目の値より前にアクセスがあったとき:作り直さずに、すぐキャッシュを返します
- 1つ目と2つ目の値のあいだにアクセスがあったとき:古い値を返し、あとで値を作り直す処理(遅らせて動かす関数)を、返事を返した後に動くよう登録します
- 2つ目の値のあとにアクセスがあったとき:期限切れとして、すぐ作り直します。返事は遅くなることがあります
$value = Cache::flexible('users', [5, 10], function () {
return DB::table('users')->get();
});
取り出して、消す#
キャッシュから取り出して、そのまま消したいときは pull を使います。get と同じく、無ければ null が返ります。
$value = Cache::pull('key');
$value = Cache::pull('key', 'default');
キャッシュに保存する#
Cache ファサードの put で保存します。
Cache::put('key', 'value', $seconds = 10);
保存する秒数を渡さないと、期限なしで保存されます。
Cache::put('key', 'value');
秒数の整数の代わりに、期限の時刻を表す DateTime も渡せます。
Cache::put('key', 'value', now()->plus(minutes: 10));
無いときだけ保存する#
add は、キャッシュにまだ無いときだけ保存します。実際に保存できたら true、そうでなければ false を返します。add は、途中で割り込まれない処理(アトミックな操作)です。
Cache::add('key', 'value', $seconds);
保存の期限をのばす#
touch を使うと、すでにあるキャッシュの期限(TTL)をのばせます。キャッシュがあって、期限をのばせたら true、無ければ false を返します。
Cache::touch('key', 3600);
期限の時刻をはっきり決めたいときは、DateTimeInterface・DateInterval・Carbon のどれかを渡せます。
Cache::touch('key', now()->addHours(2));
ずっと保存する#
forever は、キャッシュをずっと保存します。期限が切れないので、消したいときは forget で手で消します。
Cache::forever('key', 'value');
補足
Memcached ドライバーでは、「ずっと」保存した値も、キャッシュの大きさの上限に達すると消されることがあります。
キャッシュから消す#
forget で、キャッシュの値を消せます。
Cache::forget('key');
期限の秒数に、0 か負の数を渡しても消えます。
Cache::put('key', 'value', 0);
Cache::put('key', 'value', -5);
キャッシュ全体を空にするには flush を使います。
Cache::flush();
キャッシュの中の、アトミックロック(下の「アトミックロック」を見る)をすべて消すには flushLocks を使います。
Cache::flushLocks();
注意
flush は、設定した「プレフィックス」(キーの前に付ける印)を無視して、キャッシュのすべてのデータを消します。ほかのアプリと共有しているキャッシュを空にするときは、よく考えてください。
キャッシュのメモ化#
メモ化とは、一度取った値をその場で覚えておくことです。memo ドライバーを使うと、取り出したキャッシュの値を、1回のリクエスト(またはジョブ)のあいだだけ、メモリに置いておけます。同じ処理の中で、同じ値のためにキャッシュを何度も読まなくて済み、速くなります。
メモ化したキャッシュを使うには、memo を呼びます。
use Illuminate\Support\Facades\Cache;
$value = Cache::memo()->get('key');
memo には、キャッシュのストアの名前も渡せます。メモ化の下で使う置き場を決めます。
// 標準のストアを使う
$value = Cache::memo()->get('key');
// Redis のストアを使う
$value = Cache::memo('redis')->get('key');
あるキーの最初の get は、キャッシュのストアから値を取ります。同じリクエストやジョブの中の2回目からは、メモリから取ります。
// キャッシュを読む
$value = Cache::memo()->get('key');
// キャッシュを読まない。メモ化された値を返す
$value = Cache::memo()->get('key');
put・increment・remember など、値を変えるメソッドを呼ぶと、メモ化された値は自動で捨てられ、変更は元のストアにまかされます。
Cache::memo()->put('name', 'Taylor'); // 元のキャッシュに書く
Cache::memo()->get('name'); // 元のキャッシュを読む
Cache::memo()->get('name'); // メモ化された値。キャッシュは読まない
Cache::memo()->put('name', 'Tim'); // メモ化された値を捨て、新しい値を書く
Cache::memo()->get('name'); // また元のキャッシュを読む
cache ヘルパー関数#
Cache ファサードのほかに、どこからでも呼べる cache 関数でも、キャッシュを読み書きできます。文字列を1つ渡すと、そのキーの値が返ります。
$value = cache('key');
キーと値の配列と、期限を渡すと、その期間だけ保存します。
cache(['key' => 'value'], $seconds);
cache(['key' => 'value'], now()->plus(minutes: 10));
引数なしで呼ぶと、Illuminate\Contracts\Cache\Factory の実体が返るので、ほかのキャッシュのメソッドも呼べます。
cache()->remember('users', $seconds, function () {
return DB::table('users')->get();
});
補足
グローバルな cache 関数の呼び出しをテストするときは、ファサードをテストするときと同じように、Cache::shouldReceive が使えます。
基本のメソッドの一覧#
| メソッド | 説明 |
|---|---|
get |
値を取り出す。無ければ null(初期値も渡せる) |
has |
値があるかを調べる。中身が null なら false |
increment |
整数の値を増やす |
decrement |
整数の値を減らす |
remember |
取り出す。無ければクロージャの結果を保存して返す |
rememberWithWarmth |
remember と同じ。キャッシュから取れたかの真偽値も返す |
rememberForever |
取り出す。無ければ期限なしで保存して返す |
flexible |
古い値を返しながら、裏で作り直す |
pull |
取り出して、消す |
put |
保存する。期限を渡さなければ、期限なし |
add |
無いときだけ保存する。保存できたら true |
touch |
保存してある値の期限をのばす |
forever |
期限なしで保存する |
forget |
値を消す |
flush |
キャッシュ全体を空にする(プレフィックスを無視する) |
flushLocks |
アトミックロックをすべて消す |
memo |
1回のリクエストのあいだ、値をメモリに置く |
キャッシュのタグ#
注意
file・dynamodb・database・storage ドライバーでは、キャッシュのタグは使えません。
キャッシュのタグを使うと、関係のあるキャッシュに同じ印(タグ)を付けて、印ごとにまとめて消せます。タグ付きのキャッシュを使うときは、タグの名前を順に並べた配列を tags に渡します。次は、タグ付きのキャッシュに put で値を入れる例です。
タグ付きで保存する#
use Illuminate\Support\Facades\Cache;
Cache::tags(['people', 'artists'])->put('John', $john, $seconds);
Cache::tags(['people', 'authors'])->put('Anne', $anne, $seconds);
タグ付きの値を取り出す#
タグ付きで保存した値は、そのときと同じタグを渡さないと取り出せません。保存したときと同じ順番のタグの配列を tags に渡し、取りたいキーを get に渡します。
$john = Cache::tags(['people', 'artists'])->get('John');
$anne = Cache::tags(['people', 'authors'])->get('Anne');
タグ付きの値を消す#
タグ(またはタグの配列)が付いた値を、まとめて消せます。次のコードは、people・authors のどちらかのタグ、または両方が付いたキャッシュをすべて消します。つまり、Anne も John も消えます。
Cache::tags(['people', 'authors'])->flush();
これに対して、次のコードは authors のタグが付いた値だけを消します。Anne は消えますが、John は残ります。
Cache::tags('authors')->flush();
アトミックロック#
注意
この機能を使うには、アプリの標準のキャッシュのドライバーを、memcached・redis・dynamodb・database・file・array のどれかにする必要があります。また、すべてのサーバーが、同じ中心のキャッシュサーバーとつながっている必要があります。
アトミックロックは、「同時に1つだけが取れる鍵」です。複数のサーバーや処理が同時に動いても、順番の取り合い(競合)を心配せずに、鍵を使えます。たとえば、Laravel Cloud は、サーバーで一度に1つの遠隔の作業だけが動くように、アトミックロックを使っています。鍵は Cache::lock で作って管理します。
ロックを使う#
use Illuminate\Support\Facades\Cache;
$lock = Cache::lock('foo', 10);
if ($lock->get()) {
// 10 秒のあいだロックを取れた...
$lock->release();
}
get にクロージャを渡すこともできます。クロージャが終わると、Laravel が自動でロックを手放します。
Cache::lock('foo', 10)->get(function () {
// 10 秒のあいだロックを取れて、終わったら自動で手放す...
});
ロックを頼んだとき、すぐには取れないことがあります。そのときは、決めた秒数だけ待たせられます。待っても取れなければ、Illuminate\Contracts\Cache\LockTimeoutException が出ます。
use Illuminate\Contracts\Cache\LockTimeoutException;
$lock = Cache::lock('foo', 10);
try {
$lock->block(5);
// 最大 5 秒待って、ロックを取れた...
} catch (LockTimeoutException $e) {
// ロックを取れなかった...
} finally {
$lock->release();
}
block にクロージャを渡すと、上の例を短くできます。決めた秒数のあいだロックを取ろうとし、クロージャが終わると、自動で手放します。
Cache::lock('foo', 10)->block(5, function () {
// 最大 5 秒待って、10 秒のあいだロックを取れた...
});
別のプロセスでロックを手放す#
ロックをあるプロセス(動いているプログラム)で取り、別のプロセスで手放したいことがあります。たとえば、Web のリクエストでロックを取り、そのリクエストが動かしたキューのジョブの終わりで手放す場合です。このときは、ロックの「持ち主のトークン」をジョブに渡します。ジョブは、そのトークンで、ロックを作り直します。
次の例では、ロックを取れたときだけ、キューのジョブを動かします。ロックの owner メソッドで、持ち主のトークンをジョブに渡します。
$podcast = Podcast::find($id);
$lock = Cache::lock('processing', 120);
if ($lock->get()) {
ProcessPodcast::dispatch($podcast, $lock->owner());
}
アプリの ProcessPodcast ジョブの中では、持ち主のトークンを使って、ロックを元に戻して手放せます。
Cache::restoreLock('processing', $this->owner)->release();
いまの持ち主を気にせずに、ロックを手放したいときは forceRelease を使います。
Cache::lock('processing')->forceRelease();
ロックの期限をのばす#
いま持っているロックの期限をのばしたいときは、refresh を使います。秒数を渡さなければ、ロックのはじめの長さが使われます。長くかかる仕事で、とても長い期限のロックを取る代わりに、短いロックを取って、ときどきのばしたいときに便利です。
$lock = Cache::lock('generate-reports', 60);
if ($lock->get()) {
foreach ($reports as $report) {
$report->generate();
// ロックをさらに 60 秒のばす
$lock->refresh();
}
$lock->release();
}
同時に動く数を制限する#
アトミックロックの機能には、クロージャが同時に動く数を制限する方法もあります。システム全体で、同時に1つしか動かしたくないときは withoutOverlapping を使います。
Cache::withoutOverlapping('foo', function () {
// 最大 10 秒待って、ロックを取れた...
});
ふつうは、クロージャが終わるまでロックを持ち、ロックを取るために最大 10 秒待ちます。これらの値は、引数で変えられます。
Cache::withoutOverlapping('foo', function () {
// 最大 5 秒待って、120 秒のあいだロックを取れた...
}, lockFor: 120, waitFor: 5);
待つ時間のうちにロックを取れなかったときは、Illuminate\Contracts\Cache\LockTimeoutException が出ます。
同時に動く数の上限を決めたいときは、funnel を使います。funnel は、ロックに対応したキャッシュのドライバーなら使えます。
Cache::funnel('foo')
->limit(3)
->releaseAfter(60)
->block(10)
->then(function () {
// 同時実行のロックを取れた...
}, function () {
// 同時実行のロックを取れなかった...
});
funnel のキーは、制限したいもの(資源)の名前です。limit は同時に動ける最大の数、releaseAfter は、取った枠を自動で手放すまでの安全のための秒数、block は、空いた枠を待つ秒数です。
失敗のときのクロージャを渡さず、例外で受けたいときは、2つ目のクロージャを省きます。待つ時間のうちに枠を取れないと、Illuminate\Cache\Limiters\LimiterTimeoutException が出ます。
use Illuminate\Cache\Limiters\LimiterTimeoutException;
try {
Cache::funnel('foo')
->limit(3)
->releaseAfter(60)
->block(10)
->then(function () {
// 同時実行のロックを取れた...
});
} catch (LimiterTimeoutException $e) {
// 同時実行のロックを取れなかった...
}
決まったキャッシュのストアを使いたいときは、そのストアの funnel を呼びます。
Cache::store('redis')->funnel('foo')
->limit(3)
->block(10)
->then(function () {
// "redis" ストアで同時実行のロックを取れた...
});
補足
funnel を使うには、キャッシュのストアが Illuminate\Contracts\Cache\LockProvider インターフェイスを持っている必要があります。ロックに対応していないストアで使うと、BadMethodCallException が出ます。
| メソッド | 説明 |
|---|---|
Cache::lock |
ロックを作る。名前と秒数を渡す |
get |
ロックを取る。取れたら true |
block |
決めた秒数まで待って、ロックを取る。取れなければ例外 |
release |
ロックを手放す |
owner |
ロックの持ち主のトークンを返す |
Cache::restoreLock |
トークンを使って、ロックを作り直す |
forceRelease |
持ち主を気にせずに、ロックを手放す |
refresh |
いま持っているロックの期限をのばす |
withoutOverlapping |
システム全体で、同時に1つだけクロージャを動かす |
funnel |
クロージャが同時に動く数を制限する |
キャッシュのフェイルオーバー#
failover ドライバーは、キャッシュの置き場が使えなくなったとき、自動でほかの置き場に切りかえてくれます。いちばん手前の置き場が、何かの理由で失敗したら、Laravel は、設定した一覧の次の置き場を自動で試します。キャッシュが止まると困る本番の環境で、止まらない(可用性を保つ)ようにするのに役立ちます。
failover の置き場は、ドライバーに failover を指定し、順に試す置き場の名前の配列を書いて作ります。Laravel の config/cache.php には、見本が入っています。
'failover' => [
'driver' => 'failover',
'stores' => [
'database',
'array',
],
],
failover ドライバーの置き場を作ったら、アプリの .env ファイルで、標準のキャッシュの置き場にそれを指定します。そうしないと、フェイルオーバーは働きません。
CACHE_STORE=failover
キャッシュの操作が失敗して、フェイルオーバーが働くと、Laravel は Illuminate\Cache\Events\CacheFailedOver イベントを出します。これを受け取れば、キャッシュの置き場の失敗を、記録したり知らせたりできます。
独自のキャッシュドライバーを作る#
ドライバーを書く#
独自のキャッシュドライバーを作るには、まず Illuminate\Contracts\Cache\Store コントラクト(守るべき約束ごと)を実装します(約束ごとにあるメソッドを、自分のクラスに全部書くことです)。MongoDB のキャッシュなら、次のような形になります。
<?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, $seconds) {}
public function putMany(array $values, $seconds) {}
public function increment($key, $value = 1) {}
public function decrement($key, $value = 1) {}
public function forever($key, $value) {}
public function touch($key, $seconds) {}
public function forget($key) {}
public function flush() {}
public function getPrefix() {}
}
あとは、これらのメソッドを、MongoDB の接続を使って実装するだけです。実装の見本は、Laravel のフレームワークのソースコードにある Illuminate\Cache\MemcachedStore を見てください。実装が終わったら、Cache ファサードの extend で、ドライバーの登録を済ませます。
Cache::extend('mongo', function (Application $app) {
return Cache::repository(new MongoStore);
});
補足
独自のドライバーのコードを置く場所に迷ったら、app フォルダの中に Extensions という名前空間(クラスの住所のような名前)を作る方法があります。ただし、Laravel は、アプリのフォルダの構成を固く決めていません。好きなように整えてかまいません。
| メソッド | 説明 |
|---|---|
get |
値を取り出す |
many |
複数のキーの値をまとめて取り出す |
put |
値を保存する |
putMany |
複数の値をまとめて保存する |
increment |
値を増やす |
decrement |
値を減らす |
forever |
期限なしで保存する |
touch |
期限をのばす |
forget |
値を消す |
flush |
すべて消す |
getPrefix |
キーの前に付ける印(プレフィックス)を返す |
ドライバーを登録する#
独自のドライバーを Laravel に登録するには、Cache ファサードの extend を使います。登録は、booting コールバック(あとで呼んでもらうために渡しておく関数)の中でします。なぜなら、ほかのサービスプロバイダ(アプリの起動のときに、道具を登録する場所)が、自分の boot メソッドの中でキャッシュを読むことがあるからです。booting を使うと、すべてのサービスプロバイダの register が呼ばれたあと、boot が呼ばれる直前に登録できます。booting コールバックは、App\Providers\AppServiceProvider の register メソッドに書きます。
<?php
namespace App\Providers;
use App\Extensions\MongoStore;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
$this->app->booting(function () {
Cache::extend('mongo', function (Application $app) {
return Cache::repository(new MongoStore);
});
});
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
// ...
}
}
extend の1つ目の引数は、ドライバーの名前です。config/cache.php の driver に書く名前と同じにします。2つ目の引数は、Illuminate\Cache\Repository を返すクロージャです。クロージャには、$app(サービスコンテナの実体)が渡されます。
登録が済んだら、CACHE_STORE 環境変数、または config/cache.php の default を、作ったドライバーの名前に変えます。
キャッシュのイベント#
キャッシュの操作のたびに動かしたいコードがあるときは、キャッシュが出すイベント(「〜が起きた」という知らせ)を受け取ります。イベントは、すべて Illuminate\Cache\Events の中にあります。
| イベント | 説明 |
|---|---|
CacheHit |
キャッシュに値があった |
CacheMissed |
キャッシュに値が無かった |
RetrievingKey |
値を1つ取り出そうとしている |
RetrievingManyKeys |
複数の値を取り出そうとしている |
WritingKey |
値を1つ書こうとしている |
WritingManyKeys |
複数の値を書こうとしている |
KeyWritten |
値を書けた |
KeyWriteFailed |
値を書けなかった |
ForgettingKey |
値を消そうとしている |
KeyForgotten |
値を消せた |
KeyForgetFailed |
値を消せなかった |
CacheFlushing |
キャッシュ全体を空にしようとしている |
CacheFlushed |
キャッシュ全体を空にできた |
CacheFlushFailed |
キャッシュ全体を空にできなかった |
CacheLocksFlushing |
ロックをすべて消そうとしている |
CacheLocksFlushed |
ロックをすべて消せた |
CacheLocksFlushFailed |
ロックをすべて消せなかった |
速さを上げたいときは、キャッシュのイベントを止められます。config/cache.php の、そのストアの設定で、events を false にします。
'database' => [
'driver' => 'database',
// ...
'events' => false,
],
関連するページ#
公式ドキュメント(英語)
2026年10月5日時点の内容をもとに、日本語でまとめています。