Классы кэша в Laravel

Источник: «Laravel Cache Classes»
Использование специализированных классов для управления кэшем.

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

Для начала просто использовал фасад Cache в Laravel, как показано ниже:

Cache::remember(
'unique-key',
60, // время жизни кэша 60 секунд
fn () => $this->operationToBeCached()
);

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

Допустим, этот кэш предназначен для пользователя, и когда данные, связанные с ним, изменятся, нужно будет забыть кэш. Это несложно, просто используйте метод forget.

Cache::forget('unique-key');

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

Для решения этой проблемы я создал класс CacheHelper.

<?php

namespace App\Cache;

use Illuminate\Support\Facades\Cache;

abstract class CacheHelper
{
protected string $key; // Ключ кэша
protected int $ttl = 60; // Время жизни

public function getKey(): string
{
return $this->key;
}

public function value(): mixed // Хранение и извлечение значения из кэша
{
return Cache::remember(
$this->getKey(),
$this->ttl,
fn () => $this->generate()
);
}

public function forget(): bool // Забыть значение из кэша
{
return Cache::forget($this->getKey());
}

abstract protected function generate(): mixed; // Абстрактный метод генерации значения кэша
}

Класс CacheHelper абстрактный, поэтому его необходимо расширить и включить в него метод generate. Я также создал трейт, позволяющий задавать уникальные ключи с помощью ID.

<?php

namespace App\Cache;

trait CacheIdentifier
{
protected int|string|null $identifier = null;

public function getKey(): string
{
return sprintf($this->key, $this->identifier); // Прикрепление идентификатора к ключу кэша.
}
}

Ниже приведён пример, как его можно расширить.

<?php

namespace App\Cache;

use App\Models\User;
use Illuminate\Support\Collection;

class UserExpensiveComputationCache extends CacheHelper
{
use CacheIdentifier;

protected string $key = 'expensive_computation_:%s';
protected int $ttl = 60;

public function __construct(protected readonly User $user)
{
$this->identifier = $user->id; // identifier - это ID пользователя, привязанный к ключу
}

public static function make(User $user): static
{
return new static($user); // Простой хелпер для создания нового экземпляра
}

protected function generate(): Collection
{
return $this->user->expensiveComputation();
}
}

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

<?php

$user = User::find(1);
$value = UserExpensiveComputationCache::make($user);

Класс UserExpensiveComputationCache запомнит значение для пользователя, которое я ему передал.

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

<?php

UserExpensiveComputationCache::make($user)->forget();

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

Мне удалось довольно быстро собрать класс CacheHelper, и он решил мою проблему, позволяя избежать использования магических строк во всем приложении и легко управлять очисткой кэша при необходимости. Использование специализированных классов для кэширования элементов — это не то, что я использовал раньше. Пожалуйста, напишите мне, если видели что-то подобное или есть другие идеи и стратегии для управления кэшем. Спасибо, за чтение!

Дополнительные материалы

Предыдущая Статья

Как решить проблему PHP Curl с центром сертификации HTTPS в Windows

Следующая Статья

Масштабируемый CSS с архитектурой ITCSS