Кэш с мемоизацией в Laravel,  Cache::memo() , считывает ключ из хранилища кэша один раз и возвращает его из памяти в течение оставшейся части запроса или задачи. Начиная с Laravel 13.33, он также работает с тегами кэша, поэтому вы можете мемоизировать значения с тегами с помощью  Cache::memo()->tags() .

Это помогает, когда один и тот же помеченный тегом ключ считывается в рамках одного запроса множество раз. Проверка прав доступа может выполняться для каждого вызова  can()  и каждой директивы  @can  во вьюхе, и без мемоизации каждый такой случай приводит к обращению к хранилищу кэша.

#Мемоизация поиска по тегам

Вызовите  tags()  для мемоизированного кэша и используйте его как любой другой кэш с тегами:

use Illuminate\Support\Facades\Cache;
 
public function getPermissions(User $user): Collection
{
    return Cache::memo()
        ->tags(['permissions', "user:{$user->id}"])
        ->remember(
            "permissions:{$user->id}",
            now()->addHour(),
            fn () => $this->loadPermissionsFromDatabase($user)
        );
}
 

Первый вызов в рамках запроса считывает данные из хранилища кэша замыкания или выполняет его при промахе кэша. Последующие вызовы с теми же тегами и ключом возвращают значение из памяти.

До того как мемоизированный кэш стал поддерживать теги, приходилось самостоятельно оборачивать кэш с тегами в хранилище  array :

return Cache::store('array')->tags('permission_cache')->rememberForever($cacheKey,
    fn () => Cache::tags($this->cacheTags($user))->remember(
        $cacheKey,
        config('auth.permissions.default_cache_time'),
        fn () => $this->loadPermissionsFromDatabase($user)
    )
);
 

#Запись и очистка

Методы, которые изменяют значение, выполняют запись в кэш с тегами и удаляют мемоизированную копию этого ключа, поэтому при следующем чтении запрос снова пойдет в хранилище:

$cache = Cache::memo()->tags(['permissions']);
 
$cache->get('permissions:1');           // Reads from the cache store
$cache->get('permissions:1');           // Reads from memory
 
$cache->put('permissions:1', $updated); // Writes to the store, forgets the memoized value
$cache->get('permissions:1');           // Reads from the cache store again
 

Это касается  put() ,  putMany() ,  add() ,  increment() ,  decrement() ,  forever() ,  touch()  и  forget() . Вызов  flush()  для мемоизированного кэша с тегами сбрасывает теги в хранилище и очищает мемоизированные значения с тегами.

#Когда это использовать

Мемоизированный кэш хранит то, что текущий запрос уже прочитал. Если воркер очереди или другой запрос изменит значение, текущий запрос этого изменения не увидит.

Я бы использовал его для значений, которые не меняются во время выполнения запроса, таких как права доступа или настройки. Счетчики и все, что обновляется другими процессами прямо посреди запроса, лучше оставлять в обычном кэше.

Мемоизированные значения сбрасываются в начале каждого запроса или задачи, поэтому долгоиграющие воркеры не сохраняют устаревшие данные между задачами.

#Дополнительное чтение