Interna des Ersetzungsflusses
Diese Seite dokumentiert das Laufzeitverhalten für Leser, die das Plugin verstehen oder erweitern möchten. Nichts davon ist nötig, um es zu konfigurieren.
Event-Subscriber
Abschnitt betitelt „Event-Subscriber“Das Plugin hört auf drei Storefront-Page-Loaded-Events und zwei Entity-Loaded-Events:
| Event | Handler | Seitenart |
|---|---|---|
ProductPageLoadedEvent | onProductPageLoaded | Produktdetail |
NavigationPageLoadedEvent | onNavigationPageLoaded | Kategorie / Listing |
LandingPageLoadedEvent | onLandingPageLoaded | Landing-Seite |
CategoryEvents::CATEGORY_LOADED_EVENT | onCategoryEntityLoaded | CMS-Navigation-Widget (XHR) |
LandingPageEvents::LANDING_PAGE_LOADED_EVENT | onLandingPageEntityLoaded | Landing-Seiten-Entity-Load |
Alle fünf liegen in Subscriber\PageLoadedSubscriber.
Die Page-Loaded-Handler decken normale Storefront-Navigation ab. Die beiden Entity-Loaded-Handler decken den CMS-Navigation-Widget-XHR ab (den Aufruf, mit dem Ihre Storefront Kategorie-Inhalte lazy nachlädt) sowie direkte Landing-Seiten-Entity-Loads, sodass sich die Ersetzung konsistent verhält, egal ob das Layout als Teil der Hauptseite oder als Teil eines Widget-XHRs gerendert wird.
Die Matching-Schleife
Abschnitt betitelt „Die Matching-Schleife“Für jeden relevanten Request macht der Handler grob:
salesChannelId = aus dem Request auflösen1. Hat das Basislayout das Ersetzungsmodus-Tor passiert? - Produktseite → ProductPageReplaceModeEnum (4 Werte) - Kategorienseite → NavigationPageReplaceModeEnum (3 Werte) - Landing-Seite → LandingPageReplaceModeEnum (3 Werte) Falls nein → return.
2. alternativeTypes = SettingsService::getAlternativeReplaceTypes(baseType, salesChannelId) Falls leer → return.
3. Jede p2lab_cms_assigner_cms_page_to_rule durchlaufen, deren cmsPage.type IN alternativeTypes liegt: - Sortiert nach rule.priority ASC (Shopwares Standard-Sortierung). - In Seiten von 100 (LIMIT_PER_REQUEST), bis zu 500 insgesamt (LIMIT_TOTAL). - Zeilen nach cmsPageId gruppieren — einem Layout können mehrere Regeln angehängt sein.
4. Für jede cmsPageId RuleConditionService::match(rules, page, salesChannelContext) aufrufen: - Alle angehängten Regeln müssen passen (UND-Semantik). - Eine Regel wird aus ihren Bedingungen gebaut, gefiltert auf ConditionNameEnum::CONDITIONS und CONTAINERS. - Der Matcher verzweigt nach Seitentyp → ProductRuleScope / CategoryRuleScope / LandingRuleScope.
5. Erster Treffer gewinnt. Das Plugin lädt die CmsPage über SalesChannelCmsPageLoaderInterface mit einem um Produkt / Kategorie / landingPage gebauten EntityResolverContext und weist sie dann dem Page-Objekt zu.Die Tabelle p2lab_cms_assigner_cms_page_to_rule
Abschnitt betitelt „Die Tabelle p2lab_cms_assigner_cms_page_to_rule“Das Plugin speichert Regel-zu-Layout-Zuweisungen in einer einzelnen Junction-Tabelle. Jede Zeile enthält:
id— Primärschlüssel.cms_page_id+cms_page_version_id— das Alternativlayout.rule_id— die Regel, von der es abhängt.
Ein Layout mit N angehängten Regeln hat N Zeilen; eine Regel, die M Layouts angehängt ist, hat M Zeilen. In beide Richtungen lesbar.
Rule Scopes
Abschnitt betitelt „Rule Scopes“Das Plugin definiert drei eigene Rule Scopes (unter Rule\Scope\), damit seine eigenen Bedingungen (und die Standard-Shopware-Bedingungen) introspektieren können, was betrachtet wird:
ProductRuleScope— hält dasSalesChannelProductEntityplus den Sales-Channel-Kontext. Wird von Produktseiten-Handlern verwendet und vonInCategoryRule/InCategoryWithChildrenRulegeteilt, wenn sie gegen diecategoryIdseines Produkts auswerten.CategoryRuleScope— hält diecategoryIdplus den Sales-Channel-Kontext. ExposedisHomepage()(verwendet vonIsHomepageRule).LandingRuleScope— hält dieLandingPage-Page plus den Sales-Channel-Kontext.
Alle drei erben von AbstractRuleScope, das den SalesChannelContext und das Kategorie-Repository hält (damit Regeln, die den Baum durchlaufen, suchen können).
Eigene Rule-Klassen
Abschnitt betitelt „Eigene Rule-Klassen“Das Plugin bringt drei eigene Rule-Klassen mit (unter Rule\):
IsHomepageRule— boolesche Prüfung gegenCategoryRuleScope::isHomepage(). Gibt auf Nicht-Kategorie-Scopesfalsezurück.InCategoryRule— UUID-Vergleich gegen diecategoryIdsdes Produkts oder die eigeneidder Kategorie.InCategoryWithChildrenRuleerweitertInCategoryRule— durchläuft zusätzlich den Kategorien-path(Shopware speichert die Vorfahrenkette als|id1|id2|id3|), um Nachkommen zu matchen.
Es gibt auch Rule\Container\MatchAllRule — einen Stand-in für Shopwares “Alle-Positionen-Container”, dessen produkt-only-Semantik im Kontext einer CMS-Layout-Auswahl keinen Sinn ergibt. Das Plugin ersetzt sie durch eine eigene Implementierung, die nur dann true zurückgibt, wenn jede Kindregel gegen den aktuellen Scope passt.
Explizit ausgeschlossene Bedingungen
Abschnitt betitelt „Explizit ausgeschlossene Bedingungen“ConditionNameEnum definiert zwei Arrays: CONTAINERS und CONDITIONS. Alles, was nicht in diesen Arrays ist, wird beim Bauen einer Regel stillschweigend ignoriert. Die Ausschlussliste ist absichtlich breit — viele Standard-Shopware-Bedingungen (Warenkorbsummen, Line-Item-Attribute, Versandart) zielen auf den Checkout-Flow und haben beim Auswählen eines Layouts für eine noch nicht aufgebaute Seite keinen Sinn.
Was genau unterstützt wird, siehe Eigene Regelbedingungen.
Wann die Entity-Loaded-Handler greifen
Abschnitt betitelt „Wann die Entity-Loaded-Handler greifen“onCategoryEntityLoaded ist am subtilsten. Er läuft auf category.loaded-Events und agiert nur, wenn der Request wie ein CMS-Navigation-Widget-XHR aussieht — der Pfad matcht ^/widgets/cms/navigation/<32-hex>$ und der Query-String trägt navigationId + cms-page-id. So hält das Plugin die Ersetzung konsistent, wenn die Storefront den Inhalt einer Kategorie über den Widget-XHR holt (zusätzlich zum initialen Page-Render).
Er macht dieselbe Modus-Prüfung wie der Haupt-onNavigationPageLoaded-Handler, bevor er die cmsPageId der Entity überschreibt.
onLandingPageEntityLoaded läuft auf landing_page.loaded-Events und wendet das Standard-Landing-Seiten-Layout an, wenn die Landing-Seite kein eigenes Layout hat. Dies ist der Einstiegspunkt für die Default-Layout-Einstellung der Karte Landing-Seite.
Was das Plugin NICHT macht
Abschnitt betitelt „Was das Plugin NICHT macht“- Es modifiziert nicht die CMS-Seite selbst — nur welche
CmsPageEntitygerendert wird. - Es berührt nicht die Kategorie- / Produkt- / Landing-Seiten-Entity in der Datenbank — die Überschreibung passiert im Speicher, pro Request.
- Es cached seine Entscheidungen nicht; jeder Request wertet die Regeln neu aus. Die Repository-Suche trifft die Standard-Caches von Shopware, aber die Regel-Auswertung ist pro Request.
Verwandt
Abschnitt betitelt „Verwandt“- Performance — Limits und worauf zu achten ist.
- Eigene Regelbedingungen — die unterstützte Liste mit Semantik.