web-dev-qa-db-fra.com

Comment utiliser correctement les cookies? (Contexte de brindille et de cache)

Dans mon projet actuel, je dois modifier les modèles de nœuds en fonction de la page de destination précédemment visitée. Mon idée est que, lorsqu'un visiteur visite l'une de ces pages de destination, un cookie est défini et les modèles de nœuds suivants sont modifiés en fonction de ce cookie.

J'ai trois pages de vue servant de points d'entrée pour mes visiteurs:
myproject.com/tv
myproject.com/mobile
myproject.com/infopoint

Dans le prétraitement du thème, je vérifie/configure un cookie et attribue une variable de modèle. Les modèles Twig font des modifications mineures en fonction de cette variable:

function MYTHEME_preprocess(array &$variables, $hook) {
  $router = \Drupal::routeMatch();

  if ($route = $router->getRouteObject()) {
    $view_id = $route->getDefault('view_id');
    $display_id = $route->getDefault('display_id');
    $view_display_plugin = $route->getOption('_view_display_plugin_id');

    if ($view_id && $view_display_plugin === 'page') {
      if ($view_id == 'slide') {
        user_cookie_save(['device' => 'tv']);
        $variables['MYTHEME']['device'] = 'tv';
      }
      elseif ($view_id == 'tile' && $display_id == 'mobile') {
        user_cookie_save(['device' => 'mobile']);
        $variables['MYTHEME']['device'] = 'mobile';
      }
      elseif ($view_id == 'tile' && $display_id == 'infopoint') {
        user_cookie_save(['device' => 'infopoint']);
        $variables['MYTHEME']['device'] = 'infopoint';
      }
    }
  }

  // user_cookie_save prefixes all cookie names with 'Drupal.visitor.'
  if (isset($_COOKIE['Drupal.visitor.device']) && 
    in_array($_COOKIE['Drupal.visitor.device'], ['tv', 'mobile', 'infopoint'])) {
         // I'm doing design modifications in my Twig templates depending on this variable
        $variables['MYTHEME']['device'] = $_COOKIE['Drupal.visitor.device'];
    }
  }
}

Dans services.yml, j'ai activé le contexte de cache des cookies

parameters:
  renderer.config:
    required_cache_contexts: ['languages:language_interface', 'theme', 'user.permissions', 'url.site', 'cookies:Drupal.visitor.device']

Dans mes modèles Twig j'ai plusieurs morceaux de code comme celui-ci:

{% if MYTHEME.device == 'tv' %}
   <!-- code here -->
{% else %}
   <!-- other design here -->
{% endif %}

Malheureusement, le code ne fonctionne pas vraiment. Sur les pages d'entrée, la variable de thème device est toujours correcte, mais le cookie n'est pas mis à jour (il semble que seule la première occurrence non mise en cache définit le cookie. J'ai même la situation étrange que le cookie et twig variable are not equal.). Sur les modèles de nœuds, la variable de thème n'est pas définie correctement.

Des idées sur la façon de faire fonctionner le code ci-dessus?

PS: En raison des vues lentes avec des calculs de géo-distance, la désactivation du cache n'est pas une option, je dois également fournir des pages en cache pour les utilisateurs anonymes.

2
Hudri

J'ai mis à jour le code dans la question, le code fonctionne maintenant. C'était presque terminé, j'avais cependant fait quelques erreurs simples:

  1. Même lorsque vous fournissez un contexte de cache approprié, vous devez toujours désactiver le module Internal page cache. Seul le module Internal dynamic page cache Est autorisé.
  2. user_cookie_save() préfixe le nom du cookie avec Drupal.visitor. C'est le vrai nom que vous verrez également dans la console de développement de votre navigateur. Mais lors de la vérification des noms de cookies en PHP, les points et les espaces sont convertis en traits de soulignement. Cela signifie que l'utilisation de user_cookie_save(['mycookie' => 'some_value']); crée un cookie avec un "vrai" nom de Drupal.visitor.mycookie, Mais en PHP
    • votre code de modèle/module doit vérifier
      if ($_COOKIE['Drupal_visitor_mycookie'])
    • et vous devez également utiliser le nom de soulignement dans services.yml
      required_cache_contexts: ['cookies:Drupal_visitor_device', '...other_stuff...']
  3. Ne définissez pas la valeur du cookie et vérifiez cette valeur de cookie mise à jour dans la même demande:
    user_cookie_save(['mycookie' => 'new_value'])
    mettra immédiatement à jour le cookie dans le navigateur client, mais PHP code dans la même requête comme
    if ($_COOKIE['Drupal_visitor_mycookie'])
    renverra toujours la valeur d'origine de la demande précédente.
5
Hudri