search
LoginSignup
4

posted at

updated at

Organization

Laravel9からEloquentのアクセサでキャッシュが使えるようになった

Laravel9からEloquentのアクセサ/ミューテタでキャッシュが使えるようになったので試してみました。

検証バージョン

PHP8.1.6
Laravel9.16.0

キャッシュの指定方法

アクセサを定義する時にshouldCacheメソッドを呼んで指定します。
※Laravel9からアクセサ/ミューテタの記法が変わりました

User.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'email',
        'sei',
        'mei',
    ];
    
    /**
     * フルネームを取得するAttribute
     * @return Attribute
     */
    public function fullName(): Attribute
    {
        // Attribute生成時にshouldCacheメソッドを呼ぶ
        return Attribute::make(
            get: function ($value, $attributes) {
                // 起動されたことを表すためにログを埋め込み
                \Log::info('get fullName start');
                return $attributes['sei'] . ' ' . $attributes['mei'];;
            },
        )->shouldCache();
    }
}

試してみる

id sei mei
1 山田 一郎

上記のようなデータがある場合に、フルネームを取得した後にキャッシュが効いているか試してみます。

SampleController.php
class SampleController extends Controller
{
    public function index()
    {
        $user = User::find(1);
        \Log::info($user->fullName);

        // アクセサにかかわるプロパティを変更してもキャッシュが効いていてアクセサの値は変わらない
        $user->sei = '鈴木';
        \Log::info($user->fullName);

        return;
    }
}

埋め込んだログは下記のように表示され、キャッシュされていることがわかります。

laravel.log
local.INFO: get fullName start  
local.INFO: 山田 一郎  
local.INFO: 山田 一郎  

キャッシュが使えるようになって何が嬉しいか

計算量が多い、かつアクセサ呼ばれる回数が多い場合にキャッシュすることで1度呼んだら後は値を参照するだけなので処理速度の改善に繋がると思います。

注意点

アクセサは最初に取得した値を保持し続けるため、DB更新やプロパティが変更された際に値の矛盾が生じるので使い所は考える必要があります。

まとめ

計算量が多いアクセサを実装するシーンは少ないと思いますが、上手く使うと処理速度改善に繋がると思うので使うチャンスがある場合はぜひ使ってみてください!

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4