Torna al blog

Hook di preprocess di Drupal: perché il contesto di cache `url.path` è importante

2025-09-068 min di lettura

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 o route
  • Utente corrente → aggiungi user (o contesti più granulari come user.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 di url.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 o route.
  • 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.