logo

Extra Block Types (EBT) - Neue Erfahrung im Layout Builder❗

Extra Block Types (EBT) - gestylte, anpassbare Blocktypen: Diashows, Registerkarten, Karten, Akkordeons und viele andere. Eingebaute Einstellungen für Hintergrund, DOM Box, Javascript Plugins. Erleben Sie die Zukunft der Layouterstellung schon heute.

Demo EBT-Module EBT-Module herunterladen

❗Extra Absatztypen (EPT) - Erfahrung mit neuen Absätzen

Extra Paragraph Types (EPT) - analoger, auf Absätzen basierender Satz von Modulen.

Demo EPT-Module EPT-Module herunterladen

Scroll
19/06/2025, by Ivan
Cache-Kontexte = (Request-)Kontextabhängigkeiten
Cache-Kontexte sind ähnlich wie der HTTP-Header Vary.

Warum?

Cache-Kontexte definieren, wie kontextabhängige Varianten von etwas, das gecacht werden soll, erstellt werden. Der Code zur Erstellung von Caches wird dadurch leichter lesbar, und dieselbe Logik muss nicht an jeder Stelle wiederholt werden, an der gleiche Kontextänderungen benötigt werden.

Beispiele:

  • Die Ausgabe einiger Daten hängt vom aktiven Theme ab, und es werden unterschiedliche Ergebnisse für verschiedene Themes ausgegeben. Dann verwendet man Cache mit Abhängigkeit vom Cache-Kontext des Themes.
  • Wenn ein Render-Array eine personalisierte Nachricht zeigt, hängt das Rendering vom Benutzer ab. Dann hängt der Cache vom Cache-Kontext des Benutzers ab.
  • Typischerweise: Wenn eine kostenintensive Information von der Serverumgebung abhängt, wird dafür ebenfalls ein Cache-Kontext verwendet.

Wie funktioniert das?

Ein Cache-Kontext ist ein String, der auf einen der verfügbaren Cache-Kontext-Services verweist (siehe unten).

Cache-Kontexte werden als Mengen von Strings übergeben (Reihenfolge spielt keine Rolle) und als string[] dargestellt. Das sind Mengen, da ein Cache-Element von mehreren Cache-Kontexten abhängen kann (variieren kann).

Cache-Kontexte stammen normalerweise aus dem Request-Kontext-Objekt (also aus der Anfrage). Der Großteil der Webanwendungsumgebung stammt aus dem Request-Kontext. HTTP-Antworten werden größtenteils abhängig von den Eigenschaften der sie auslösenden HTTP-Anfragen erzeugt.

Das bedeutet jedoch nicht, dass Cache-Kontexte immer von der Anfrage kommen müssen – sie können auch vom ausgeführten Code abhängen, z.B. vom Kontext deployment_id.

Zweitens sind Cache-Kontexte als Hierarchie beschrieben. Ein einfaches Beispiel: Wenn etwas für jeden Benutzer unterschiedlich ist, brauchen wir nicht nur Zugriffsrechte, denn es gibt Unterschiede pro Benutzer. Für Zugriffsrechte wird der Cache für jede Berechtigung gesetzt. Wenn ein Seitenabschnitt für jeden Benutzer unterschiedlich ist und ein anderer für Berechtigungen, muss Drupal klug genug sein, um Unterschiede nur pro Benutzer zu verwenden. Drupal nutzt also die Hierarchie-Information, um unnötige Cache-Variationen zu vermeiden.

Syntax

  • Punkte trennen Elternelemente von Kinderelementen
  • Ein pluraler Cache-Name zeigt an, dass ein Parameter verwendet werden kann: Nach einem Doppelpunkt wird der gewünschte Parameter angegeben (wenn kein Parameter angegeben ist, werden alle möglichen Parameter gesammelt, z.B. alle Query-Argumente)

Cache-Kontexte im Drupal 8 Core

Der Drupal 8 Core liefert folgende Cache-Kontext-Hierarchie:

cookies
  :name
headers
  :name
ip
languages
  :type
protocol_version // Ab Version 8.9.x verfügbar.
request_format
route
  .book_navigation
  .menu_active_trails
    :menu_name
  .name
session
  .exists
theme
timezone
url
  .path
    .is_front // Ab Version 8.3.x verfügbar.
    .parent
  .query_args
    :key
    .pagers
      :pager_id
  .site
user
  .is_super_user
  .node_grants
    :operation
  .permissions
  .roles
    :role

Hinweis: Um den Cache-Kontext url.path.is_front in älteren Versionen zu verwenden, siehe Änderungsmitteilung.

Überall wo Cache-Kontexte verwendet werden, wird diese gesamte Hierarchie genutzt, was drei Vorteile bietet:

  • Keine Mehrdeutigkeit: Es ist klar, worauf sich der übergeordnete Cache-Kontext bezieht, egal wo er verwendet wird.
  • Vergleich (und Reduzierung) von Cache-Kontexten wird einfacher: Sind z.B. a.b.c und a.b vorhanden, so beinhaltet a.b automatisch a.b.c, sodass a.b.c weggelassen werden kann.
  • Man muss nicht dafür sorgen, dass jeder Baumlevel im gesamten Baum eindeutig ist.

Beispiele aus der Hierarchie:

  • theme (abhängig vom aktiven Theme)
  • user.roles (abhängig von der Rollenkombination)
  • user.roles:anonymous (abhängig davon, ob der aktuelle Nutzer die Rolle „anonym“ hat oder nicht, d.h. ob er anonym ist)
  • languages (unterscheidet alle Sprachtypen: Interface, Inhalt ...)
  • languages:language_interface (abhängig von der Interface-Sprache - LanguageInterface::TYPE_INTERFACE)
  • languages:language_content (abhängig von der Inhaltssprache - LanguageInterface::TYPE_CONTENT)
  • url (abhängig von der gesamten URL)
  • url.query_args (abhängig von der gesamten Query-String)
  • url.query_args:foo (abhängig vom Query-Argument foo)
  • protocol_version (abhängig von HTTP 1 versus 2)

Optimierung / Zusammenfassung / Vereinfachung von Cache-Kontexten

Drupal nutzt automatisch die Hierarchie-Information, um Cache-Kontexte zu vereinfachen. Wenn sich z.B. ein Teil der Seite für den Nutzer ändert (Cache-Kontext user) und ein anderer für Berechtigungen (Cache-Kontext user.permissions), macht es keinen Sinn, das Endergebnis für Berechtigungen zu ändern, da Berechtigungsänderungen pro Benutzer variieren.
Anders gesagt: optimize([user, user.permissions]) = [user].

Obwohl user.permissions spezifischer ist, optimiert Drupal user.permissions so, dass Änderungen an Berechtigungen nicht dazu führen, dass user.permissions für jede Seite geladen wird. Das heißt, auch wenn sich Berechtigungen ändern, wird dieselbe gecachte Version weiterverwendet, obwohl sie sich ändern sollte.

Deshalb können Cache-Kontexte, die von sich ändernder Konfiguration abhängen, Cache-Metadaten binden: Cache-Tags und max-age. Wenn so ein Cache-Kontext optimiert wird, werden seine Cache-Tags mit dem Cache-Element assoziiert. Somit wird der Cache ungültig, sobald die zugewiesenen Berechtigungen sich ändern.

(„Caching“ bedeutet grundsätzlich „Vermeidung unnötiger Berechnungen“. Daher kann die Kontext-Optimierung als Caching des Ergebnisses der getContext()-Methode eines CacheContext-Services gesehen werden. Dies ist ein implizites Caching (Wert wird verworfen statt gespeichert), aber der Effekt ist derselbe: Beim Cache-Hit wird getContext() nicht aufgerufen, Berechnungen werden vermieden. Und da wir Dinge cachen, verknüpfen wir deren Cachebarkeit, weshalb wir bei Cache-Kontexten Tags und max-age binden.)

Ein komplexeres Beispiel sind node grants. Diese sind benutzerspezifisch, daher hat der Cache-Kontext der Node-Berechtigungen die Form user.node_grants. Allerdings sind Node-Berechtigungen oft sehr dynamisch (z.B. zeitabhängig, wechseln alle paar Minuten), abhängig von den node grant Hooks der Seite. Daher ist es besser, für diesen Cache-Kontext max-age = 0 zu setzen, d.h. er ist nicht cachebar (nicht optimiert). Daraus folgt: optimize([user, user.node_grants]) = [user, user.node_grants].

Einige Seiten können die Standard-Implementierung des Node Permissions Cache-Kontexts überschreiben und stattdessen max-age = 3600 setzen, wenn alle node grant Hooks erlauben, die Zugriffsresultate bis zu einer Stunde zu cachen. In diesem Fall gilt: optimize([user, user.node_grants]) = [user].

Wie erkennt, definiert und erstellt man Cache-Kontexte?

Cache-Kontexte sind Services mit dem Tag cache.context. Daher kann jedes Modul Cache-Kontexte hinzufügen. Sie implementieren \Drupal\Core\Cache\Context\CacheContextInterface oder \Drupal\Core\Cache\Context\CalculatedCacheContextInterface (für Cache-Kontexte mit Parametern, d.h. mit Suffix :parameter).

Um alle verfügbaren Cache-Kontexte zu finden, suchen Sie einfach alle Implementierungen von CacheContextInterface und CalculatedCacheContextInterface. (In PHPStorm: Typ-Hierarchie → Untertyp-Hierarchie; in NetBeans: Rechtsklick auf Interface → Verwendung suchen → Alle Untertypen finden.)

Alternativ können Sie die Drupal-Konsole nutzen (drupal debug:cache:context), um alle aktuellen Cache-Kontexte Ihrer Site oder Anwendung anzuzeigen:

$ drupal debug:cache:context
 Context ID               Label                             Class path                                               
 cookies                  HTTP-Cookies                      Drupal\Core\Cache\Context\CookiesCacheContext            
 headers                  HTTP-Header                       Drupal\Core\Cache\Context\HeadersCacheContext            
 ip                       IP-Adresse                        Drupal\Core\Cache\Context\IpCacheContext                 
 languages                Language                         Drupal\Core\Cache\Context\LanguagesCacheContext          
 request_format           Anfrageformat                    Drupal\Core\Cache\Context\RequestFormatCacheContext      
 route                    Route                            Drupal\Core\Cache\Context\RouteCacheContext              
 route.book_navigation    Buchnavigation                   Drupal\book\Cache\BookNavigationCacheContext             
 route.menu_active_trails Aktiver Menüpfad                 Drupal\Core\Cache\Context\MenuActiveTrailsCacheContext

In jeder dieser Klassen finden Sie Kommentare wie bei \Drupal\Core\Cache\Context\UserCacheContext:

Cache context ID: 'user'.

Das bedeutet, dass 'user' der tatsächliche Cache-Kontext ist, den Sie im Code angeben können. (Alternativ können Sie in der *.services.yml-Datei nachschauen, wo diese Klasse als Service registriert ist und den Service-Identifier ansehen.)

Tipp: Eine aktuelle vollständige Liste aller Core Cache-Kontexte erhalten Sie, indem Sie alle Services mit dem Tag cache_context anschauen!

Der Service-Identifier ist standardisiert. Er beginnt immer mit cache_context., gefolgt von den Eltern des Cache-Kontexts und dem Namen des Cache-Kontexts. Zum Beispiel:

cache_context.route.book_navigation:
  class: Drupal\book\Cache\BookNavigationCacheContext
  arguments: ['@request_stack']
  tags:
    - { name: cache.context }

Dies definiert den Cache-Kontext route.book_navigation.

Debugging

Die oben genannten Informationen sind hilfreich beim Debuggen von gecachten Inhalten. Ein weiterer wichtiger Punkt: Angenommen, etwas wird mit Cache-Keys ['foo', 'bar'] und Cache-Kontext ['languages:language_interface', 'user.permissions', 'route'] gecacht. Dann wird das Cache-Element mit folgender Cache-ID (CID) im Cache-Container gespeichert:

foo:bar:[languages:language_interface]=en:[user.permissions]=A_QUITE_LONG_HASH:[route]=myroute.ROUTE_PARAMS_HASH

Das bedeutet:

  • Cache-Schlüssel werden in der angegebenen Reihenfolge zuerst aufgelistet
  • Cache-Kontexte werden alphabetisch sortiert und als Teile der CID in der Form [<cache context name>]=<cache context value> angehängt
  • Alle Teile der CID sind durch Doppelpunkte getrennt

Das erleichtert die Analyse und das Debuggen von Caches.

Header (Debugging)

Zuletzt: Es ist einfach ersichtlich, von welchen Cache-Kontexten eine Antwort abhängt (und somit variiert), indem man nur den Header X-Drupal-Cache-Contexts betrachtet!

Hinweis: Wenn Sie diese Header nicht sehen, müssen Sie Drupal für die Entwicklungsumgebung konfigurieren.

Dynamischer Seiten-Cache

Die umfassende Nutzung von Cache-Kontexten in Drupal 8 ermöglicht es, dass Drupal 8 mit aktiviertem dynamischem Seiten-Cache (früher „Smart Cache“ genannt) ausgeliefert wird.

Interner Seiten-Cache

Beachten Sie, dass der interne Seiten-Cache davon ausgeht, dass alle Seiten, die anonymen Nutzern bereitgestellt werden, identisch sind, unabhängig von den implementierten Cache-Kontexten. Wenn Sie Cache-Kontexte verwenden möchten, um Inhalte für anonyme Nutzer zu variieren, muss dieses Modul deaktiviert werden, was die Leistung beeinträchtigen kann.

Siehe auch

Source URL:

Drupal’s online documentation is © 2000-2020 by the individual contributors and can be used in accordance with the Creative Commons License, Attribution-ShareAlike 2.0. PHP code is distributed under the GNU General Public License.