設定

Laravelは多くのキャッシュシステムに読み書きしやすい、統一したAPIを提供します。キャッシュの設定はconfig/cache.phpで設定します。アプリケーション全体でデフォルトとして使用するキャッシュドライバをこのファイルの中で指定します。MemcachedRedisなど、人気のあるキャッシュシステムをLaravelは最初からサポートしています。

キャッシュ設定ファイルは、様々な他のオプションも含んでいます。コメントで説明してありますので、よく読んで確認してください。Laravelのデフォルトとして、fileキャッシュドライバが設定されています。ファイルシステムへオブジェクトをシリアライズして保存します。大きなアプリケーションではMemecachedやAPCのような、より堅牢なドライバを使うことをおすすめします。複数のドライバを使用するキャッシュ設定も可能です。

ドライバ事前要件

データベース

データベースをキャッシュドライバに使用する場合、キャッシュアイテムを構成するテーブルを用意する必要があります。このテーブルの「スキーマ」を定義するサンプルを見てください。

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

Tip!! 正確なスキーマのマイグレーションを生成するために、php artisan cache:table Artisanコマンドを使用することもできます。

Memcached

Memcachedキャッシュを使用する場合は、Memcached PECLパッケージをインストールする必要があります。全Memcachedサーバは、config/cache.php設定ファイルにリストしてください。

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

さらに、UNIXソケットパスへ、hostオプションを設定することもできます。これを行うにはportオプションに0を指定してください。

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

Redis

LaravelでRedisキャシュを使用する場合、predis/predisパッケージ(~1.0)をComposerでインストールする必要があります。

Redisの設定についての詳細は、Laravelドキュメントページを読んでください。

キャシュの使用法

キャッシュインスタンスの取得

Illuminate\Contracts\Cache\FactoryIlluminate\Contracts\Cache\Repository契約は、Laravelのキャッシュサービスへのアクセスを提供します。Factory契約は、アプリケーションで定義している全キャッシュドライバへのアクセスを提供します。Repository契約は通常、cache設定ファイルで指定している、アプリケーションのデフォルトキャッシュドライバの実装です。

しかし、このドキュメント全体で使用している、Cacheファサードも利用できます。Cacheファサードは裏で動作している、Laravelキャッシュ契約の実装への便利で簡潔なアクセスを提供しています。

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
    /**
     * アプリケーションの全ユーザリストの表示
     *
     * @return Response
     */
    public function index()
    {
        $value = Cache::get('key');

        //
    }
}

複数のキャッシュ保存先へのアクセス

Cacheファサードのstoreメソッドを使い、様々なキャッシュ保存域へアクセスできます。storeメソッドに渡すキーは、cache設定ファイルのstores設定配列にリストしている保存域の一つです。

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

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

キャッシュからアイテム取得

Cacheファサードのgetメソッドは、キャッシュからアイテムを取得するために使用します。アイテムがキャッシュに存在していない場合は、nullが返されます。アイテムが存在していない時に返したい、カスタムデフォルト値をgetメソッドの第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')) {
    //
}

値の増減

incrementdecrementメソッドはキャッシュの整数アイテムの値を調整するために使用します。両方のメソッドともそのアイテムの値をどのくらい増減させるかの増分をオプションの第2引数に指定できます。

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

取得不可時更新

キャッシュからアイテムを取得しようとして、指定したアイテムが存在しない場合は、デフォルト値を保存したい場合もあるでしょう。たとえば、全ユーザをキャッシュから取得しようとし、存在していない場合はデータベースから取得しキャシュへ追加したい場合です。Cache::rememberメソッドを使用します。

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

キャッシュに存在しない場合、rememberメソッドに渡された「クロージャ」が実行され、結果がキャッシュに保存されます。

取得後削除

キャッシュからアイテムを取得した後に削除したい場合は、pullメソッドを使用します。getメソッドと同様にキャッシュにアイテムが存在していない場合は、nullが返ります。

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

キャシュへアイテム保存

Cacheファサードのputメソッドにより、キャッシュにアイテムを保存できます。キャッシュにアイテムを保存するときには、何分保存するかを指定する必要があります。

Cache::put('key', 'value', $minutes);

どのくらいでアイテムが無効になるかを分数で指定する代わりに、キャッシュされたアイテムの有効期限を示すDateTimeインスタンスを渡すこともできます。

$expiresAt = Carbon::now()->addMinutes(10);

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

非存在時保存

addメソッドはキャッシュに保存されていない場合のみ、そのアイテムを保存します。キャッシュに実際にアイテムが追加された場合はtrueが返ってきます。そうでなければfalseが返されます。

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

アイテムを永遠に保存

foreverメソッドはそのアイテムをキャッシュへ永遠に保存します。こうした値は有効期限が切れないため、forgetメソッドを使用し、削除する必要があります。

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

Tip!! Memcachedドライバーを使用する場合、キャッシュが最大値に達すると、"forever"を指定したアイテムも削除されます。

キャシュからのアイテム削除

forgetメソッドでキャッシュからアイテムを削除します。

Cache::forget('key');

キャッシュ全体をクリアしたい場合はflushメソッドを使います。

Cache::flush();

Note: flushメソッドは、キャッシュのプレフィックスを考慮せずに、キャッシュから全アイテムを削除します。他のアプリケーションと共有するキャッシュを削除するときは、利用を熟考してください。

cacheヘルパ

CacheファサードとCache契約に付け加え、キャッシュからのデータ取得/保存を行う、グローバルcache関数も使用できます。cache関数を文字列引数一つで呼び出す場合、指定したキーの値を返します。

$value = cache('key');

キー/値ペアの配列と、有効期間を関数へ渡す場合、指定期間の間、値をキャッシュへ保存します。

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

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

グローバルcache関数への呼び出しをテストする場合、ファサードのテストと同様に、Cache::shouldReceiveメソッドを使います。

キャシュタグ

Note: filedatabaseキャッシュドライバ使用時、キャッシュタグはサポートされません。また、"forever"を使い、複数のタグをつけたキャッシュを使用する場合、古いレコードを自動的にパージするmemcachedのようなドライバがパフォーマンス的に最適です。

タグ付けキャッシュアイテムの保存

キャシュタグにより、キャッシュ中の関連するアイテムへタグ付けできます。その後、指定したタグがつけられたキャッシュの値を全部削除できます。タグを順番に指定する配列を渡すことで、タグ付けしたキャッシュへアクセスできます。例としてタグ付けしたキャッシュにアクセスし、キャッシュへ値をputしてみましょう。

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

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

タグ付けキャッシュアイテムへのアクセス

タグ付けしたキャッシュアイテムを取得するには、tagsメソッドに同じ順序でタグのリストを渡し、続けてgetメソッドで取得したいキーを指定します。

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

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

タグ付けキャッシュアイテムの削除

タグ一つ、もしくはタグのリストに結びついた全アイテムを一度に消去することができます。たとえば、次の実行文はpeopleauthorsのどちらか、または両方にタグ付けされたキャッシュを全部削除します。ですから、AnneJohnは両方共キャッシュから削除されます。

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

対照的に、次の実行分ではauthorsにタグ付けしたキャッシュのみ削除されますので、Anneが削除され、Johnは残ります。

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

カスタムキャッシュドライバの追加

ドライバープログラミング

カスタムキャッシュドライバを作成するには、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, $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() {}
}

これらのメソッドをMongoDB接続を用い、実装するだけです。各メソッドをどのように実装するかの例は、フレームワークのIlluminate\Cache\MemcachedStoreのソースコードを参照してください。実装を完了したら、ドライバを登録します。

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

Tip!! カスタムキャッシュドライバーをどこに設置するか迷っているなら、appディレクトリ下にExtensionsの名前空間で作成できます。しかし、Laravelはアプリケーション構造を強制していませんので、自分の好みに合わせてアプリケーションを自由に構築できることを忘れないでください。

ドライバ登録

Laravelにカスタムキャッシュドライバを登録するには、Cacheファサードのextendメソッドを使います。新しくインストールしたLaravelに含まれている、デフォルトのApp\Providers\AppServiceProviderbootメソッドで、Cache::extendを呼び出せます。もしくは、拡張を設置するために自身のサービスプロバイダを作成することもできます。config/app.phpプロバイダ配列に、そのプロバイダを登録し忘れないようにしてください。

<?php

namespace App\Providers;

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

class CacheServiceProvider extends ServiceProvider
{
    /**
     * サービス起動後の登録処理
     *
     * @return void
     */
    public function boot()
    {
        Cache::extend('mongo', function ($app) {
            return Cache::repository(new MongoStore);
        });
    }

    /**
     * コンテナへ結合を登録
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

extendメソッドの最初の引数はドライバ名です。これはconfig/cache.php設定ファイルの、driverオプションと対応します。第2引数は、Illuminate\Cache\Repositoryインスタンスを返すクロージャです。クロージャには、サービスコンテナインスタンスの$appインスタンスが渡されます。

拡張を登録したら、config/cache.php設定ファイルのdriverオプションへ、拡張の名前を登録してください。

イベント

全キャッシュ操作に対してコードを実行するには、キャッシュが発行するイベントを購読する必要があります。通常、イベントリスナはEventServiceProviderの中へ設置します。

/**
 * アプリケーションのイベントリスナ
 *
 * @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',
    ],
];