Сессии для анонимов и кэш.

Главные вкладки

Аватар пользователя buddy90210 buddy90210 21 февраля 2023 в 15:18

Всем привет!
Может подскажете решение или путь к нему)
При переходе на сайт в событии KernelEvents::REQUEST я проверяю существует ли сессия для пользователя.

<?php
$session 
= \Drupal::request()->getSession();
$location_info $session->get('user_geo_info');
?>

Для авторизованных пользователей все отлично работает. А вот для анонимов данное значение попадает в кэш и всегда одинаково для всех анонимов.

Подскажите как можно создавать индивидуальные сессии для анонимов? Здесь даже скорей не в сессиях проблема, а в кэшировании кода для анонимов, потому что дамп для анонима только один раз отрабатывает. Может есть какой то метод инвалидировать кэш если анонимный пользователь сменился?

Лучший ответ

Аватар пользователя OldWarrior OldWarrior 21 февраля 2023 в 16:40
1

buddy90210 wrote: Для авторизованных пользователей все отлично работает. А вот для анонимов данное значение попадает в кэш и всегда одинаково для всех анонимов.

Вообще - что-то странно. Сессии не должны кешироваться. Возможно, причина в том, что вы читаете сессию в слишком ранней точке? Насколько я понял, используется подписка на события с помощью EventSubscriberInterface . И, кстати, тогда уместнее получать Request из объекта входящего $event, а не через статический вызов \Drupal::request():

<?php
public function onRequest(RequestEvent $event) {
  ...
  
/** @var Request $request */
  
$request $event->getRequest();
  
$session $request->getSession();
  ...
}
?>

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

Комментарии

Аватар пользователя OldWarrior OldWarrior 21 февраля 2023 в 16:40
1

buddy90210 wrote: Для авторизованных пользователей все отлично работает. А вот для анонимов данное значение попадает в кэш и всегда одинаково для всех анонимов.

Вообще - что-то странно. Сессии не должны кешироваться. Возможно, причина в том, что вы читаете сессию в слишком ранней точке? Насколько я понял, используется подписка на события с помощью EventSubscriberInterface . И, кстати, тогда уместнее получать Request из объекта входящего $event, а не через статический вызов \Drupal::request():

<?php
public function onRequest(RequestEvent $event) {
  ...
  
/** @var Request $request */
  
$request $event->getRequest();
  
$session $request->getSession();
  ...
}
?>

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

Аватар пользователя buddy90210 buddy90210 21 февраля 2023 в 18:29

Да все верно) во всем был виноват контроллер в котором я записывал значение) Спасибо!

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

Попутный вопрос, у меня зашла дискуссия, что не очень это хорошая идея что то записывать в сессию анонима, так ли это? Аргумент, что со временем база разрастется до безумных размеров из-за кеша анонимов, так ли это?

Аватар пользователя OldWarrior OldWarrior 21 февраля 2023 в 20:48

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

Вообще - какая-то не совсем понятная техника - в том плане, что инвалидируется весь кеш для данного тега (а, кстати, тогда что именно является кеш-тегом в данном случае?). Мне кажется, уместнее вводить кеш-контекст (зависимость от входящих параметров). Только в вашем случае, видимо, уместнее брать IP посетителя-анонима, если речь о геолокации. Или сам обнаруженный город, если он обнаружен корректно.

В общем, тут что-то непонятно, как это у вас сделано.

Аватар пользователя voviko voviko 21 февраля 2023 в 16:44

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

<?php 
    $build
['#cache']['context'][] = 'cookies:user_geo_info';
?>

более подробно тут
Например для блока можно просто добавить код, естественно в куках хранится, например, локация "Москва" и тп

<?php
 
public function getCacheContexts() {
     return 
Cache::mergeContexts(parent::getCacheContexts(), ['cookies:user_geo_info']);
 }
?>