Hooks de pré-traitement Drupal : pourquoi le contexte de cache `url.path` est important
Lorsque vous modifiez la sortie dans un hook de prétraitement en fonction de la route ou du chemin actuel, vous devez également indiquer au cache de rendu de Drupal ce qui fait varier cette sortie. Sinon, le premier résultat rendu peut être mis en cache et réutilisé partout.
La situation
Considérez un prétraitement personnalisé pour le bloc de marque qui affiche un nom de site différent sur les nœuds de blog :
getRouteName();
// Vérifie si nous sommes sur une page de blog
if ($route_name === 'entity.node.canonical') {
$node = $route_match->getParameter('node');
if ($node && $node->bundle() === 'blog') {
// Sur les pages de blog, modifie le nom du site pour afficher "BONJOUR LE MONDE"
$variables['site_name'] = 'BONJOUR LE MONDE';
}
}
// Sur la page d'accueil et les autres pages, conserve le nom de site d'origine
}
Sans la ligne qui ajoute le contexte de cache ($variables['#cache']['contexts'][] = 'url.path';
), Drupal peut mettre en cache la première version qu'il rend (par exemple, la version du blog) et la réutiliser sur chaque page. C'est pourquoi vous avez vu le même texte partout.
Pourquoi cela se produit
- Mise en cache du rendu : Drupal met en cache les tableaux de rendu pour des raisons de performance.
- Sortie variable : Si la sortie change selon le chemin ou la route, la clé de cache doit inclure cette variabilité.
- Contextes de cache : L'ajout de
url.path
(ou d'un contexte plus spécifique) indique à Drupal de maintenir des variations de cache distinctes par chemin.
Est-ce vrai pour tous les hooks de prétraitement ?
Oui, la règle s'applique à toute sortie rendue qui varie. Les hooks de prétraitement modifient souvent les tableaux de rendu ou les variables de modèle qui font partie du cache de rendu. Si votre logique varie selon :
- Chemin ou route → ajoutez
url.path
ouroute
- Utilisateur actuel → ajoutez
user
(ou des contextes plus granulaires commeuser.roles
) - Langue → ajoutez
languages:language_interface
- Thème ou point d'arrêt → ajoutez
theme
,responsive_image_style
, etc.
Le prétraitement en soi n'a rien de spécial ; ce qui importe, c'est de savoir si le tableau de rendu résultant doit être mis en cache différemment entre les requêtes. Si la sortie varie, déclarez les bons contextes de cache.
Choisir le bon contexte de cache
- Privilégiez la précision : Si vous dépendez du nœud canonique, envisagez
route
au lieu deurl.path
pour éviter une fragmentation inutile du cache (par exemple, les chaînes de requête ou les alias). - Blocs basés sur des entités : Lorsque vous dépendez d'une entité (comme un nœud), ajoutez des dépendances de cache pour que les modifications soient purgées correctement :
$variables['#cache']['tags'][] = 'node:' . $node->id();
- Max-age : Laissez
max-age
à sa valeur par défaut (permanente) sauf si la sortie expire réellement.
Alternative plus sûre : Dériver du tableau de rendu
Au lieu d'utiliser des variables globales, vous pouvez également attacher des métadonnées de cache à l'aide de CacheableMetadata
pour fusionner les contextes et les balises en toute sécurité :
addCacheContexts(['route']);
$route_match = \Drupal::routeMatch();
if ($route_match->getRouteName() === 'entity.node.canonical') {
$node = $route_match->getParameter('node');
if ($node && $node->bundle() === 'blog') {
$variables['site_name'] = 'BONJOUR LE MONDE';
$cacheable->addCacheTags(['node:' . $node->id()]);
}
}
$cacheable->applyTo($variables);
}
Liste de contrôle
- La sortie change-t-elle selon le chemin ou la route ? Ajoutez
url.path
ouroute
. - Dépend-elle d'une entité ? Ajoutez des balises de cache pour cette entité.
- Varie-t-elle selon l'utilisateur ou la langue ? Ajoutez les contextes correspondants.
- Gardez
max-age
élevé ; fiez-vous aux balises pour l'invalidation.
À retenir
Oui, si votre logique de prétraitement modifie la sortie par page, vous devez déclarer les contextes de cache correspondants. Sinon, Drupal servira volontiers le même résultat mis en cache partout.