- カテゴリ: キャッシュ管理
- 掲載バージョン: Laravel 13・PHP 8.3(
php artisan tinkerで全コード例を実行確認済み) - 対象:
Cacheファサード /config/cache.php/ キャッシュタグ / キャッシュ関連Artisanコマンド - 関連:
cache()ヘルパー /config:cache/optimize - 変更履歴: Laravel 11以降、既定のキャッシュストアは「file」から「database」に変更
要点(TL;DR)
- Laravel CacheはDBアクセスや重い計算の結果を一時保存し、アプリを高速化する仕組み。
Cacheファサードで操作する - 既定ストアはLaravel 11以降「database」(それ以前は「file」)。
.envのCACHE_STOREで切り替える - 基本は
Cache::remember('key', $ttl, fn () => 重い処理())の1パターンを覚えれば大半のケースに対応できる - キャッシュタグ(
tags())はfile・databaseドライバでは非対応。array・redis・memcachedのみ利用可 - 罠:
has()/missing()は値がnullのとき「存在しない」と判定する(実機検証で確認)
Laravelのキャッシュとは?
キャッシュとは、一度取得・計算した結果を一時的に保存しておき、次回以降は同じ処理をやり直さずに済ませる仕組みです。LaravelにはCacheコンポーネントが標準搭載されており、DBクエリの結果、外部APIのレスポンス、集計処理の結果などをCacheファサード経由で簡単にキャッシュできます。
効果が大きいのは「アクセス頻度が高いのに、元データの更新頻度は低い」データです。例えばダッシュボードの集計値、カテゴリ一覧、設定値などはキャッシュとの相性が良く、DBの負荷とレスポンスタイムを同時に改善できます。逆に、リクエストごとに変わる値(ログインユーザー固有のデータなど)をキャッシュすると、古いデータを表示し続けるバグの原因になるため注意が必要です。
対応キャッシュドライバーと選び方
Laravelは複数のキャッシュストアをconfig/cache.phpで定義でき、.envのCACHE_STOREで既定ストアを切り替えます。主なドライバーの特徴は次のとおりです(キャッシュタグ対応可否は実機で例外発生の有無を確認済み)。
| ドライバー | 永続化 | 複数サーバー間共有 | タグ対応 | 主な用途 |
|---|---|---|---|---|
file | あり | 不可 | 非対応 | 単一サーバーでの手軽な利用(Laravel 10以前の既定) |
database | あり | 可(共有DB利用時) | 非対応 | 追加ミドルウェア不要。Laravel 11以降の既定 |
redis | 設定次第 | 可 | 対応 | 本番環境の第一候補。高速・タグ・アトミックロック対応 |
memcached | なし(揮発性) | 可 | 対応 | 純粋なキャッシュ専用途で高速 |
array | なし(リクエスト内のみ) | 不可 | 対応 | テスト・ローカル検証用 |
dynamodb | あり | 可 | 非対応 | AWS環境でのマネージド運用 |
実機検証メモ:新規に composer create-project laravel/laravel で作成したLaravel 13プロジェクトでは、.envの初期値が CACHE_STORE=database でした。以前の記事や書籍で「既定はfileドライバー」と書かれている場合、Laravel 10以前の情報である可能性が高いので注意してください。
設定方法(.env / config/cache.php)
# .env
CACHE_STORE=redis
CACHE_PREFIX=myapp_cache
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
databaseドライバーを使う場合、Laravel 11以降はデフォルトのマイグレーションにcacheテーブルが最初から含まれているため追加作業は不要です。Laravel 10以前のプロジェクトを移行する場合のみ、テーブル作成コマンド(make:cache-table)が必要になります。設定値そのものをキャッシュして起動を高速化したい場合はconfig:cacheコマンドを使います。
Cacheファサードの基本操作(実機検証コード)
以下はすべて php artisan tinker 上で実際に実行し、出力を確認済みのコードです。
保存・取得・削除
use Illuminate\Support\Facades\Cache;
// 保存(TTLは秒)
Cache::put('key', 'value', 60);
// 取得(なければ第2引数を返す)
Cache::get('key'); // "value"
Cache::get('missing', 'default'); // "default"
// 削除
Cache::forget('key');
Cache::get('key'); // null
remember系:重い処理を「一度だけ」実行してキャッシュする
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
// 1回目:クロージャが実行されキャッシュに保存される
$count = Cache::remember('users:count', 60, function () {
return DB::table('users')->count();
});
// 2回目(TTL内):クロージャは実行されず、キャッシュ値がそのまま返る
$count = Cache::remember('users:count', 60, function () {
return DB::table('users')->count();
});
実際にtinkerでクロージャ内に echo を仕込んで検証したところ、2回目の呼び出しではクロージャが実行されないことを確認しています。有効期限を設けず永続化したい場合は Cache::rememberForever()(別名 sear())を使います。
加算・排他的な追加・取り出し
use Illuminate\Support\Facades\Cache;
// add: キーが存在しない場合のみ保存(存在すればfalseを返す)
Cache::add('cnt', 1, 60); // true
Cache::add('cnt', 99, 60); // false(既に存在するため保存されない)
// increment / decrement
Cache::increment('cnt'); // 2
Cache::increment('cnt', 5); // 7
Cache::decrement('cnt', 2); // 5
// pull: 取得と同時に削除
$value = Cache::pull('cnt'); // 5
Cache::has('cnt'); // false
主要メソッド早見表
| メソッド | 用途 |
|---|---|
get($key, $default) | 取得。無ければ$default |
put($key, $value, $ttl) | 保存(秒指定) |
add($key, $value, $ttl) | 未存在時のみ保存 |
remember($key, $ttl, $callback) | あれば取得、無ければ実行して保存 |
rememberForever($key, $callback) | 期限なしでremember |
increment() / decrement() | 数値の加減算 |
pull($key, $default) | 取得と同時に削除 |
forget($key) / flush() | 個別削除 / 全削除 |
has($key) / missing($key) | 存在確認(null値は「なし」扱い) |
cache()ヘルパーとの違い
グローバル関数のcache()ヘルパーはCacheファサードの薄いラッパーで、機能的にはほぼ同等です。1行で完結させたい場合はcache()、IDEの型補完や可読性を重視するチーム開発ではCacheファサードが向いています。cache()ヘルパー固有の引数オーバーロード(文字列キーで取得・配列で保存)や落とし穴の詳細はcache()ヘルパーの記事で解説しています。
キャッシュタグ(tags)の使い方と罠
キャッシュタグを使うと、複数のキャッシュ項目をグループ化して一括削除できます。ただし前述のとおりfile・databaseドライバーは非対応です。
use Illuminate\Support\Facades\Cache;
Cache::tags(['people', 'artists'])->put('John', $john, 30);
// "people"タグが付いたキャッシュだけを一括削除
Cache::tags('people')->flush();
実機検証で判明した見落としやすい注意点があります。tags()に渡すタグは、同じ組み合わせ・同じ並び順でないと同一のキャッシュとして扱われません。
Cache::tags(['a', 'b'])->put('k1', 'v1', 30);
Cache::tags(['a', 'b'])->get('k1'); // "v1"(同じ並び順なのでヒット)
Cache::tags(['b', 'a'])->get('k1'); // null(並び順が違うためヒットしない)
tinkerでtags(['a','b'])とtags(['b','a'])を実際に試したところ、後者はnullを返しました。タグは配列ではなく「タグの並びそのもの」で名前空間を作る実装になっているため、タグを使う際はプロジェクト内で並び順を統一するルールを決めておくと事故を防げます。
Laravel最新版で使えるキャッシュ機能(flexible / withoutOverlapping)
Laravel 11以降で追加された、比較的新しい2つのメソッドも実機で動作確認しました。
flexible():期限切れ直前は古い値を返しつつ裏で再計算(stale-while-revalidate)
use Illuminate\Support\Facades\Cache;
// [新鮮とみなす秒数, 完全に破棄するまでの秒数] を指定
$stats = Cache::flexible('stats', [5, 30], function () {
return now()->timestamp; // 重い集計処理を想定
});
remember()との違いは、期限が近づいたときにリクエストを待たせず「今ある値をとりあえず返し、裏側で再計算する」点です。ダッシュボード集計のように多少の遅延が許容できるが、レスポンス遅延は避けたいケースに向いています。
withoutOverlapping():同じ処理の同時多重実行を防ぐ
use Illuminate\Support\Facades\Cache;
Cache::withoutOverlapping('report:monthly', function () {
// 集計などの重い処理。同じキーでの同時実行はロックで待機・排他される
return generateMonthlyReport();
}, lockFor: 5, waitFor: 3);
内部的にはキャッシュストアのアトミックロック(Store::lock())を利用しており、同じ集計処理をリクエストが重なって二重実行してしまう問題を防げます。ロック機能はdatabase・redis・memcached・arrayドライバーで利用できます。
キャッシュ関連のArtisanコマンドまとめ
デプロイ時によく使うキャッシュ系コマンドです。個別の詳細やオプションは各記事、コマンド全体の一覧はArtisanコマンド徹底解説を参照してください。
| コマンド | 内容 |
|---|---|
php artisan cache:clear | アプリケーションキャッシュ(Cacheで保存した値)を全削除 |
| config:cache | 設定ファイルを1つにまとめてキャッシュし起動を高速化 |
| config:clear | 設定キャッシュを削除 |
| view:cache | Bladeビューを事前コンパイルしてキャッシュ |
| view:clear | コンパイル済みビューを削除 |
| route:clear | ルートキャッシュを削除 |
| optimize | config・route・view等のキャッシュを一括作成 |
| optimize:clear | 上記のキャッシュを一括削除 |
| make:cache-table | databaseドライバー用のcacheテーブルのマイグレーションを生成 |
注意:cache:clearが消すのはCacheファサードで保存したアプリケーションキャッシュのみです。設定ファイルのキャッシュ(config:cache)やビューのキャッシュ(view:cache)は別物なので、デプロイ後に古い設定が反映されないときはconfig:clearやoptimize:clearまで実行できているか確認してください。
Laravelにページキャッシュ(フルページキャッシュ)はある?
Laravel自体には、レスポンス全体を丸ごと保存する「フルページキャッシュ」機能は標準搭載されていません。代わりに用意されているのは、ブラウザやCDNにキャッシュを許可するHTTPヘッダーを付与するcache.headersミドルウェアです。
use Illuminate\Http\Middleware\SetCacheHeaders;
Route::get('/profile', function () {
// ...
})->middleware('cache.headers:public;max_age=2628000;etag');
// 配列で指定することも可能(SetCacheHeaders::using()が文字列に変換)
Route::get('/profile', function () {
// ...
})->middleware(SetCacheHeaders::using(['public' => true, 'max_age' => 2628000, 'etag' => true]));
このミドルウェアはあくまでCache-Control・ETag・Last-Modifiedといったレスポンスヘッダーを付けるだけで、Laravel自身がサーバー内でレスポンスを保存するわけではありません。サーバーサイドでレスポンス全体をキャッシュしたい場合は、spatie/laravel-responsecacheのようなパッケージを追加するか、Nginx・Varnish・CloudflareなどのCDN/リバースプロキシ層でキャッシュするのが一般的です。
よくある質問
Laravelのconfig/cacheはどこにありますか?
キャッシュストアの設定ファイルはプロジェクトルートのconfig/cache.phpです。既定ストアの指定は同ファイル内の'default' => env('CACHE_STORE', 'database')で行われ、実際の値は.envのCACHE_STOREで上書きします。
Laravelでキャッシュをクリアするコマンドは?
アプリケーションキャッシュはphp artisan cache:clearです。設定・ルート・ビューなどのキャッシュも含めてまとめて削除したい場合はphp artisan optimize:clearを使うと一括で削除できます。
Laravelのページキャッシュとは?
Laravel自体にフルページキャッシュ機能はなく、一般的には「cache.headersミドルウェアでブラウザ・CDNキャッシュを許可する」「spatie/laravel-responsecache等のパッケージでレスポンスを保存する」のいずれかを指します。詳細は本記事の「ページキャッシュ」セクションを参照してください。
トラブルシュート(エラー別)
| 症状/エラー | 原因 | 対処 |
|---|---|---|
BadMethodCallException: This cache store does not support tagging. | file・databaseドライバーでtags()を使用 | redis・memcached・arrayドライバーに切り替える |
タグを指定したのにget()がnullを返す | tags()に渡した配列の並び順が保存時と異なる | 保存時と同じ順序でタグを指定する |
| デプロイ後も設定変更が反映されない | config:cache実行後、設定キャッシュが古いまま | php artisan config:clearまたはoptimize:clearを実行 |
Redis connection refused | Redisサーバー未起動・接続情報の誤り | config/database.phpのredis設定と起動状態を確認 |
| キャッシュしたはずの値が消えている | TTLを0や負数で保存した | 正の秒数を指定するか、rememberForever()を使う |
参考リンク
- Laravel Docs — Cache(公式): https://laravel.com/docs/cache
- API —
Illuminate\Cache\Repository: https://laravel.com/api/13.x/Illuminate/Cache/Repository.html - 設定ファイル
config/cache.php(公式リポジトリ): https://github.com/laravel/laravel/blob/12.x/config/cache.php - 関連記事: cache()ヘルパーの使い方 / Artisanコマンド徹底解説

コメント