Как организовать код, чтобы обернуть вокруг API систему кеша

Я создаю приложение, которое использует внешний API через уже созданную библиотеку. Давайте представим, что этот внешний сервис предоставляет информацию о погоде для данного места. У нас есть такой контроллер:

class WeatherController
{
public function show($place, WeatherLibrary $api)
{
return $api->getWeatherFor($place);
}
}

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

use Illuminate\Support\Facades\Cache;

class WeatherController
{
public function show($place, WeatherLibrary $api)
{
return Cache::get($place, function() use ($place, $api) {
$result = $api->getWeatherFor($place);
Cache::put($place, $result, 60);
return $result;
});
}
}

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

0

Решение

Исходя из комментариев епископа, вы можете создать прокси-класс, подобный этому:

class WeatherLibraryProxy
{
/**
* @var WeatherLibrary
*/
protected $driver;

public function __construct(WeatherLibrary $driver)
{
$this->driver = $driver;
}


/**
* Dynamically call the underlying api driver and cache all responses
*/
public function __call($method, $parameters)
{
$cache_key = $method . implode(',', $parameters);
$minutes = 60;
return cache()->remember($cache_key, $minutes, function () use ($method, $parameters) {
return $this->driver->$method(...$parameters);
});
}

}

Затем в вашем контроллере поменяйте введенное WeatherLibrary на ваш WeatherLibraryProxy учебный класс:

class WeatherController
{
public function show($place, WeatherLibraryProxy $api)
{
return $api->getWeatherFor($place);
}
}

я считать Служебный контейнер Laravel автоматически внедрит WeatherLibrary в конструктор вашего прокси, но если этого не произойдет, вы можете сделать что-то подобное в вашем AppServiceProvider.php:

$this->app->bind(WeatherLibraryProxy::class, function ($app) {
return new WeatherLibraryProxy(
$app->make(WeatherLibrary::class)
// OR "new WeatherLibrary($arg1, $arg2, ...)", depending how it's initialized...
);
});

который говорит Laravel, как разрешить WeatherLibraryProxy, когда это необходимо.

Подробнее об автоматическом впрыске: https://laravel.com/docs/5.7/container#automatic-injection

Теперь любые общие функции (например, проверка оставшихся ограничений скорости) можно поместить в ваш класс Proxy, который вы используете повсюду в своем приложении вместо базового класса WeatherLibrary.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]