У нас есть контроллер, который выдаёт json ответ. Добавим кеширование.
Начнем с определения контроллера. Пусть сконфигурирован следующий mymodule.routing.yml:
1 2 3 4 5 6 7 |
my-api: path: '/api/request' defaults: _controller: '\Drupal\api\Controller\PublicApi::request' _format: json requirements: _permission: 'access content' |
Это значит, что у нас создан класс PublicApi в под каталоге модуля /src/Controller/PublicApi.php. Вот его изначальный код без кеширования.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<?php namespace Drupal\api\Controller; use Drupal\Core\Controller\ControllerBase; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; class PublicApi extends ControllerBase { /* ROUTE GET api/request */ public function request() { // пример скелета ответа сервера $results = [ 'ok' => true, 'payload' => [] ]; // тут вы выполняете какую то полезную работу // наполняя payload массив ... return new JsonResponse($results); } } |
Если мы хотим закешировать ответ, то нам понадобится другой класс для формирования ответа. Это — CacheableJsonResponse. Он позволяет настроить параметры кеширования с помощью метода addCacheableDependency.
Самая простая зависимость — это от времени.
Рассмотрим, например, установку кеша на 15 минут.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
<?php namespace Drupal\api\Controller; use Drupal\api\DocumentFactory; use Drupal\Core\Controller\ControllerBase; use Symfony\Component\HttpFoundation\JsonResponse; use Drupal\Component\Utility\Xss; use Drupal\Core\Cache\CacheableJsonResponse; use Drupal\Core\Cache\CacheableMetadata; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; class PublicApi extends ControllerBase { /* ROUTE GET api/request */ public function request() { // пример скелета ответа сервера $results = [ 'ok' => true, 'payload' => [] ]; // тут вы выполняете какую то полезную работу // наполняя payload массив ... // можно по разному создавать настройки CacheableMetadata // можно так: $cacheSettings = [ '#cache' => ['max-age' => 900] ]; $cm = CacheableMetadata::createFromRenderArray($cacheSettings) // а можно вот так: $cm = new CacheableMetadata(); $cm->setCacheMaxAge(900); // ответ формируется вот так; $response = new CacheableJsonResponse($results); $response->addCacheableDependency($cm); return $response; } } |
Еще существует как минимум два типа кеширования — это Tags и Context.
Cache tags
Тэги преимущественно связаны с контентом, например пользователями или нодами.
Если вы зададите:
1 2 3 |
$cacheSettings = [ '#cache' => ['tags' => ['node:1', 'user:10']] ]; |
То кеш вашего json будет сбрасываться при изменениях node с nid = 1, и пользователя с uid = 10. При следующем запросе значение вашего json будут рассчитано вновь, а не взято из кеша.
Cache context
Контексты обычно реализуют зависимость от внешних параметров.
Например, вы желаете, чтобы ответ зависел от GET параметра — param. Тогда
1 2 3 4 5 6 7 |
// вы получаете GET параметр, как то его используете $param = $request->query->get('param', 'default-value'); ... // а далее в настройках кеша указываете этот параметр, как контекст $cm = new CacheableMetadata(); $cm->addCacheContexts(['url.query_args:param']); |
Так можно поставить кеш в зависимость от всего url или отдельных его частей.
С точки зрения безопасности, стоит подумать о допустимом разбросе значений параметра (-ов), по которым строится кеш.