もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

laravel-responsecacheを試す

はじめに

こんばんは。

今回は laravel-responsecache

を試してみました。

バージョン

Laravel Framework : 6.4.1
spatie/laravel-responsecache : 6.3

本題

インストール

$ composer require spatie/laravel-responsecache
Using version ^6.3 for spatie/laravel-responsecache
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 1 install, 0 updates, 0 removals
  - Installing spatie/laravel-responsecache (6.3.0): Loading from cache
Writing lock file
Generating optimized autoload files
ocramius/package-versions: Generating version class...
ocramius/package-versions: ...done generating version class
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
Package manifest generated successfully.

configファイル生成

config/responsecache.php
$ php artisan vendor:publish --provider="Spatie\ResponseCache\ResponseCacheServiceProvider"
Copied File [/vendor/spatie/laravel-responsecache/config/responsecache.php] To [/config/responsecache.php]
Publishing complete.
Publishing complete.

middleware

app/Http/Kernel.php

※ 明示的に このルートにのみCacheを適用させたい 場合

protected $routeMiddleware = [
   ...
   'cacheResponse' => \Spatie\ResponseCache\Middlewares\CacheResponse::class,
];

route

routes/web.php
<?php

use Illuminate\Support\Facades\Route;

Route::get('example', \App\Http\Controllers\ExampleController::class);

Controller

<?php

namespace App\Http\Controllers;

class ExampleController
{
    public function __invoke()
    {
        return view('example');
    }
}

View

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    現在の時間は {{ date('Y-m-d H:i:s') }}です。
</body>
</html>

f:id:kojirooooocks:20200215033841p:plain

表示されました。

この状態から、 /example のRouteのレスポンスをキャッシュします。

Route修正

※ この設定は 300秒 のキャッシュをする設定です。

<?php

use Illuminate\Support\Facades\Route;

Route::group(['middleware' => 'cacheResponse:300'], function (): void {
    Route::get('example', \App\Http\Controllers\ExampleController::class);
});

この状態で一度アクセスしてキャッシュを作ったあと再度リロードすると、表示が変わらないことがわかります。

キャッシュ結果はデフォルトでは file指定で、 framework/cache/* に作られます。

f:id:kojirooooocks:20200215033854p:plain

番外編

このresponsecacheは、このあたりの設定で、ajax通信には適用できません。

コレを無理やり適用するには、 CacheAllSuccessfulGetRequests.php をオーバライドして、あらたなProfile を作成する必要があります。

CustomCacheAllSuccessfulGetRequests.php

<?php
declare(strict_types=1);

namespace App\Http;

use Illuminate\Http\Request;
use Spatie\ResponseCache\CacheProfiles\CacheAllSuccessfulGetRequests;

class CustomCacheAllSuccessfulGetRequests extends CacheAllSuccessfulGetRequests
{
    /**
     * 元のメソッドではajax通信の際はキャッシュを行わない仕様になっていた。
     * それを無理やり可能にした
     * @param Request $request
     * @return bool
     */
    public function shouldCacheRequest(Request $request): bool
    {
//        if ($request->ajax()) {
//            return false;
//        }
    
        if ($this->isRunningInConsole()) {
            return false;
        }

        return $request->isMethod('get');
    }

    /**
     * もとのメソッドではログイン時にはAuthのIDをsuffixとして使おうとしていた。
     * ユーザーごとに差異がないレスポンスのキャッシュをしたい場合は、このメソッドも以下のようにオーバーライドする必要がある
     *
     * @param Request $request
     * @return string
     */
    public function useCacheNameSuffix(Request $request): string
    {
        return '';
    }
}

configファイル修正

config/responsecache.php

cache_profile 部分を作成したCustomProfileに変更

<?php

return[
    ...
    'cache_profile' => \App\Http\CustomCacheAllSuccessfulGetRequests::class,
    ...
];

これでweb以外もレスポンスキャッシュが適用できます。

終わりに

Master系のデータをキャッシュしたりもできるので、レスポンス以外にも使えるみたいです。

今の現場では使わなかったですが、汎用性が高いので、実際にプロジェクトでも使ってみたいです。

現場からは以上です。