Hook di preprocess di Drupal: perché il contesto di cache `url.path` è importante
Quando si modifica l'output in un hook di pre-elaborazione in base al percorso o alla rotta corrente, è necessario anche indicare alla cache di rendering di Drupal cosa varia in quell'output. Altrimenti, il primo risultato renderizzato potrebbe essere memorizzato nella cache e riutilizzato ovunque.
La situazione
Considera una pre-elaborazione personalizzata per il blocco di branding che mostra un nome del sito diverso sui nodi del blog:
getRouteName();
// Verifica se ci troviamo su una pagina del blog
if ($route_name === 'entity.node.canonical') {
$node = $route_match->getParameter('node');
if ($node && $node->bundle() === 'blog') {
// Nelle pagine del blog, modifica il nome del sito per mostrare "HELLO WORLD"
$variables['site_name'] = 'HELLO WORLD';
}
}
// Sulla homepage e su altre pagine, mantiene il nome del sito originale
}
Senza la riga che aggiunge il contesto della cache ($variables['#cache']['contexts'][] = 'url.path';
), Drupal potrebbe memorizzare nella cache la prima versione che renderizza (ad esempio, la versione del blog) e riutilizzarla su ogni pagina. Ecco perché vedevi lo stesso testo ovunque.
Perché succede questo
- Caching del rendering: Drupal memorizza nella cache gli array di rendering per migliorare le prestazioni.
- Output variabile: Se l'output cambia in base al percorso o alla rotta, la chiave della cache deve includere tale variabilità.
- Contesti della cache: L'aggiunta di
url.path
(o un contesto più specifico) indica a Drupal di mantenere variazioni di cache separate per ogni percorso.
Questo vale per tutti gli hook di pre-elaborazione?
Sì, la regola si applica a qualsiasi output renderizzabile che varia. Gli hook di pre-elaborazione modificano spesso array di rendering o variabili di template che diventano parte della cache di rendering. Se la tua logica varia in base a:
- Percorso o rotta → aggiungi
url.path
oroute
- Utente corrente → aggiungi
user
(o contesti più granulari comeuser.roles
) - Lingua → aggiungi
languages:language_interface
- Tema o breakpoint → aggiungi
theme
,responsive_image_style
, ecc.
La pre-elaborazione in sé non è speciale; ciò che conta è se l'array di rendering risultante debba essere memorizzato nella cache in modo diverso tra le richieste. Se l'output varia, dichiara i contesti della cache corretti.
Scegliere il contesto della cache corretto
- Preferire la precisione: Se dipendi dal nodo canonico, considera
route
invece diurl.path
per evitare frammentazioni inutili della cache (ad esempio, stringhe di query o alias). - Blocchi basati su entità: Quando dipendi da un'entità (come un nodo), aggiungi dipendenze della cache in modo che le modifiche vengano eliminate correttamente:
$variables['#cache']['tags'][] = 'node:' . $node->id();
- Max-age: Mantieni
max-age
al valore predefinito (permanente) a meno che l'output non scada veramente.
Alternativa più sicura: Derivare dall'array di rendering
Invece di utilizzare le variabili globali, puoi anche allegare metadati di cache utilizzando CacheableMetadata
per unire contesti e tag in modo sicuro:
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'] = 'HELLO WORLD';
$cacheable->addCacheTags(['node:' . $node->id()]);
}
}
$cacheable->applyTo($variables);
}
Checklist
- L'output cambia in base al percorso o alla rotta? Aggiungi
url.path
oroute
. - Dipende da un'entità? Aggiungi tag di cache per quell'entità.
- Varia in base all'utente o alla lingua? Aggiungi i contesti corrispondenti.
- Mantieni
max-age
alto; affidati ai tag per l'invalidazione.
Conclusione
Sì, se la tua logica di pre-elaborazione modifica l'output per ogni pagina, devi dichiarare i contesti della cache corrispondenti. Altrimenti, Drupal servirà felicemente lo stesso risultato memorizzato nella cache ovunque.