25 сен 2024
21
Для реализации кеширования результатов методов класса API с учётом пользователя, можно создать обёртку для существующего класса API. Эта обёртка будет перехватывать вызовы методов, проверять наличие кеша для данного пользователя и метода, и возвращать закешированный результат, если он есть. Если кеш отсутствует, обёртка будет вызывать оригинальный метод API, сохранять результат в кеш и возвращать его.
Ниже приведён пример реализации такого решения:
<?php
namespace App\Services;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Auth;
class CachedApi
{
protected $apiInstance;
protected $user;
public function __construct($apiInstance)
{
$this->apiInstance = $apiInstance;
$this->user = Auth::user();
}
public function __call($method, $arguments)
{
// Формируем уникальный ключ кеша на основе ID пользователя, названия метода и аргументов
$cacheKey = $this->getCacheKey($method, $arguments);
// Проверяем наличие данных в кеше
if (Cache::has($cacheKey)) {
return Cache::get($cacheKey);
}
// Вызываем оригинальный метод API
$result = call_user_func_array([$this->apiInstance, $method], $arguments);
// Сохраняем результат в кеш на определённое время (например, 10 минут)
Cache::put($cacheKey, $result, now()->addMinutes(10));
return $result;
}
protected function getCacheKey($method, $arguments)
{
// Получаем ID пользователя
$userId = $this->user->id;
// Сериализуем аргументы метода для уникальности ключа
$argumentsKey = md5(serialize($arguments));
// Формируем ключ кеша
return "api_cache:user_{$userId}:method_{$method}:args_{$argumentsKey}";
}
}
Объяснение
-
Класс
CachedApi
: Этот класс служит обёрткой для вашего существующего класса API. -
Свойство
$apiInstance
: Содержит экземпляр оригинального класса API. -
Свойство
$user
: Содержит информацию о текущем аутентифицированном пользователе. -
Метод
__construct($apiInstance)
: При создании экземпляра обёртки мы передаём экземпляр оригинального API-класса и получаем текущего пользователя. -
Метод
__call($method, $arguments)
: магический метод который перехватывает вызовы методов, которые не определены в классеCachedApi
. То есть все вызовы методов будут проходить через этот метод.-
Формирование ключа кеша: Используем метод
getCacheKey()
для создания уникального ключа на основе пользователя, метода и параметров запроса. -
Проверка кеша: С помощью
Cache::has($cacheKey)
проверяем, есть ли уже закешированный результат для данного ключа. - Возврат закешированного результата: Если результат есть в кеше, возвращаем его.
-
Вызов оригинального метода: Если в кеше ничего нет, вызываем оригинальный метод API с помощью
call_user_func_array()
. - Кеширование результата: Сохраняем результат в кеш с указанием времени жизни (в данном примере 10 минут).
-
Формирование ключа кеша: Используем метод
-
Метод
getCacheKey($method, $arguments)
: Создаёт уникальный ключ кеша.- ID пользователя: Используем ID пользователя для разделения кеша между разными пользователями.
- Аргументы метода: Сериализуем и хэшируем аргументы для уникальности ключа при разных параметрах.
- Формирование ключа: Возвращаем строку, которая будет уникальна для комбинации пользователя, метода и аргументов.
Использование
Теперь можно использовать обёртку CachedApi
в коде следующим образом:
<?php
use App\Services\CachedApi;
// Создаём экземпляр оригинального API-класса
$api = new ExternalApi();
// Оборачиваем его нашим кеширующим классом
$cachedApi = new CachedApi($api);
// Вызываем методы как обычно
$orders = $cachedApi->getOrders();
При этом результаты вызовов методов будут кешироваться для каждого пользователя отдельно.
Замечания
-
Настройка времени кеширования: В методе
Cache::put()
вы можете настроить время жизни кеша в соответствии с вашими требованиями. -
Исключение некоторых методов из кеширования: Если вам нужно исключить некоторые методы из кеширования, вы можете добавить условие в методе
__call()
, проверяя название метода. - Очистка кеша: При необходимости вы можете добавить методы для очистки кеша, например, при обновлении данных.
Если вы хотите очистить кеш для определённого метода и пользователя, добавим следующий метод:
<?php
public function clearCache($method, $arguments = [])
{
$cacheKey = $this->getCacheKey($method, $arguments);
Cache::forget($cacheKey);
}
Пример использования очистки кеша:
<?php
// После обновления заказов очищаем кеш
$cachedApi->clearCache('getOrders');