Zurück zum Blog

Drupal Preprocess-Hooks: Warum der `url.path`-Cache-Kontext wichtig ist

2025-09-068 Minuten Lesezeit

Wenn Sie die Ausgabe in einem Preprocess-Hook basierend auf der aktuellen Route oder dem Pfad ändern, müssen Sie dem Render-Cache von Drupal auch mitteilen, was diese Ausgabe variiert. Andernfalls kann das erste gerenderte Ergebnis zwischengespeichert und überall wiederverwendet werden.

Die Situation

Betrachten Sie ein benutzerdefiniertes Preprocess für den Branding-Block, der auf Blog-Nodes einen anderen Seitennamen anzeigt:

getRouteName();

  // Prüfen, ob wir uns auf einer Blog-Seite befinden
  if ($route_name === 'entity.node.canonical') {
    $node = $route_match->getParameter('node');
    if ($node && $node->bundle() === 'blog') {
      // Auf Blog-Seiten den Seitennamen zu "HELLO WORLD" ändern
      $variables['site_name'] = 'HELLO WORLD';
    }
  }
  // Auf der Startseite und anderen Seiten den ursprünglichen Seitennamen beibehalten
}

Ohne die Zeile, die den Cache-Kontext hinzufügt ($variables['#cache']['contexts'][] = 'url.path';), kann Drupal die erste gerenderte Version (z. B. die Blog-Version) zwischenspeichern und auf jeder Seite wiederverwenden. Deshalb sahen Sie überall denselben Text.

Warum passiert das?

  • Render-Caching: Drupal speichert Render-Arrays zur Leistungssteigerung zwischen.
  • Variierende Ausgabe: Wenn sich die Ausgabe nach Pfad oder Route ändert, muss der Cache-Schlüssel diese Variabilität enthalten.
  • Cache-Kontexte: Das Hinzufügen von url.path (oder einem spezifischeren Kontext) teilt Drupal mit, separate Cache-Variationen pro Pfad beizubehalten.

Gilt das für alle Preprocess-Hooks?

Ja, die Regel gilt für jede renderbare Ausgabe, die variiert. Preprocess-Hooks modifizieren oft Render-Arrays oder Template-Variablen, die Teil des Render-Caches werden. Wenn Ihre Logik variiert nach:

  • Pfad oder Route → url.path oder route hinzufügen
  • Aktueller Benutzer → user (oder granularere Kontexte wie user.roles) hinzufügen
  • Sprache → languages:language_interface hinzufügen
  • Theme oder Breakpoint → theme, responsive_image_style usw. hinzufügen

Preprocess selbst ist nichts Besonderes; entscheidend ist, ob das resultierende Render-Array zwischen verschiedenen Anfragen unterschiedlich zwischengespeichert werden sollte. Wenn die Ausgabe variiert, deklarieren Sie die richtigen Cache-Kontexte.

Auswahl des richtigen Cache-Kontexts

  • Präzision bevorzugen: Wenn Sie von einem kanonischen Node abhängen, ziehen Sie route anstelle von url.path in Betracht, um unnötige Cache-Fragmentierung zu vermeiden (z. B. Query-Strings oder Aliase).
  • Entitätsbasierte Blöcke: Wenn Sie von einer Entität (wie einem Node) abhängen, fügen Sie Cache-Abhängigkeiten hinzu, damit Bearbeitungen korrekt bereinigt werden: $variables['#cache']['tags'][] = 'node:' . $node->id();
  • Max-age: Behalten Sie max-age auf dem Standardwert (permanent), es sei denn, die Ausgabe läuft wirklich ab.

Sicherere Alternative: Ableiten vom Render-Array

Anstatt Globals zu verwenden, können Sie auch Cacheability-Metadaten mit CacheableMetadata anhängen, um Kontexte und Tags sicher zusammenzuführen:

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);
}

Checkliste

  • Ändert sich die Ausgabe je nach Pfad oder Route? Fügen Sie url.path oder route hinzu.
  • Hängt sie von einer Entität ab? Fügen Sie Cache-Tags für diese Entität hinzu.
  • Variiert sie je nach Benutzer oder Sprache? Fügen Sie die passenden Kontexte hinzu.
  • Halten Sie max-age hoch; verlassen Sie sich für die Invalidierung auf Tags.

Fazit

Ja – wenn Ihre Preprocess-Logik die Ausgabe pro Seite ändert, müssen Sie die entsprechenden Cache-Kontexte deklarieren. Andernfalls liefert Drupal gerne dasselbe zwischengespeicherte Ergebnis überall aus.