Markus Michalski FAQ

Textbausteine: Technische Details

Textbausteine für Shopware - Ablauf der Ersetzung, Caching, Datenmodell und Plugin-Struktur sowie die belegten Unterschiede zwischen den Plugin-Linien für Shopware 6.7 und für 6.5/6.6

English Version

Zurück zur Übersicht

Textbausteine: Technische Details

Live Demo: Teste dieses und weitere Plugins live — ohne Installation, ohne Risiko: demo.markus-michalski.net

Ablauf der Ersetzung

graph TD
    A["Twig-Filter mmd_snippets"] --> B["SnippetReplacer"]
    B --> C["SnippetParser: Regex sucht Platzhalter"]
    C --> D["SnippetRegistry: ein Abruf je Identifier"]
    D --> E{"Im Cache?"}
    E -->|"Ja"| G["Inhalt aus dem Cache"]
    E -->|"Nein"| F["Repository-Suche: Identifier und aktiv"]
    F --> G
    G --> H["HtmlSanitizer bereinigt den Inhalt"]
    H --> I["Platzhalter wird ersetzt"]
Schritt Klasse Verhalten
Filter Mmd\ProductSnippets\Twig\SnippetExtension Filter mmd_snippets und Funktion mmd_snippet. Holt den Kontext aus der aktuellen Anfrage. Ohne Anfrage wird der Text unverändert zurückgegeben.
Ersetzen Mmd\ProductSnippets\Core\Content\Snippet\SnippetReplacer Sammelt die Identifier, lädt die Bausteine, ersetzt per Regex und bereinigt jeden Inhalt mit dem HtmlSanitizer. Platzhalter ohne Treffer (unbekannt, inaktiv oder ohne Inhalt in der aktuellen Sprache) bleiben stehen.
Parsen Mmd\ProductSnippets\Core\Content\Snippet\SnippetParser Regex {{ snippet:<identifier> }} bzw. {{ textbaustein:<identifier> }}, Identifier aus a-z, A-Z, 0-9, - und _, ohne Beachtung der Groß-/Kleinschreibung.
Laden Mmd\ProductSnippets\Core\Content\Snippet\SnippetRegistry Cache-Schicht vor dem Repository mmd_product_snippet.

Caching

Invalidierung

Ein Subscriber (Mmd\ProductSnippets\Subscriber\CacheInvalidationSubscriber) hört auf die Entity-Events mmd_product_snippet.written und mmd_product_snippet.deleted:

In den letzten beiden Fällen erscheint die Änderung spätestens nach Ablauf der 3600 Sekunden oder sofort nach bin/console cache:clear. Das Plugin invalidiert außerdem nicht den HTTP-Cache der Produktseiten.

Datenmodell

Tabelle Inhalt
mmd_product_snippet id, identifier (VARCHAR 255, UNIQUE, Collation utf8mb4_unicode_ci), active (Standard 1), Zeitstempel
mmd_product_snippet_translation mmd_product_snippet_id, language_id, name, content (LONGTEXT), Zeitstempel. Löschen des Bausteins löscht kaskadierend die Übersetzungen.

Die Entity heißt mmd_product_snippet (Felder identifier, active, name, content). Alle Felder sind für die Admin-API freigegeben, sodass sich Bausteine auch darüber lesen und schreiben lassen. Eine Validierung des Identifiers gibt es dort ebenfalls nicht.

Plugin-Struktur

src/
├── MmdProductSnippets.php          # Plugin-Klasse, löscht Tabellen bei Deinstallation
├── Content/Snippet/                # Entity-Definitionen (Baustein und Übersetzung)
├── Core/Content/Snippet/           # Parser, Replacer, Registry
├── Migration/                      # Legt die beiden Tabellen an
├── Subscriber/                     # CacheInvalidationSubscriber
├── Twig/                           # SnippetExtension (Filter, Funktion)
└── Resources/
    ├── app/administration/         # Admin-Modul (Liste und Detailseite)
    ├── config/services.xml
    └── views/storefront/           # Drei Template-Overrides, unter Shopware 6.7 sind zwei wirksam

Von den drei Template-Overrides ist storefront/page/product-detail/description.html.twig unter Shopware 6.7 inaktiv, weil der Kern dieses Template nicht mehr bereitstellt. Details stehen auf der Seite Storefront-Integration.

Unterschiede der Plugin-Linie für Shopware 6.5 und 6.6

Die Linie mmd/sw66-product-snippets (Shopware ~6.5.0 || ~6.6.0) hat denselben Funktionsumfang und im Wesentlichen denselben Quelltext. Beim Vergleich beider Linien unterscheiden sich vor allem diese Punkte:

Bereich Linie 6.7 Linie 6.5 / 6.6
Composer-Paket und Shopware-Anforderung mmd/sw67-product-snippets, ~6.7.0 mmd/sw66-product-snippets, ~6.5.0 \|\| ~6.6.0
Inhalt auslesen (SnippetRegistry) Direkter Zugriff auf das Feld content der Entity (nur die aktuelle Sprache) getTranslation('content') (liest das Array translated, das die Fallback-Kette der Sprachen einbezieht)
Admin-Seiten (Liste und Detail) Seitentitel über head(), Mixins über Shopware.Mixin.getByName() Seitentitel über metaInfo(), Mixins aus dem destrukturierten Mixin
Mitgeliefertes Admin-Bundle Vite-Build unter Resources/public/administration/assets Dateien unter Resources/public/administration/js und .../css
Klassen der Entity-Schicht final, Eigenschaften identifier und mmdProductSnippetId mit typisiertem Standardwert '' nicht final, Eigenschaften ohne Standardwert
Kommentar im Template box-standard.html.twig Anmerkung zu \|raw ohne diese Anmerkung (nur Kommentar, kein Verhalten)

Der Unterschied beim Auslesen wirkt sich auf das Verhalten aus: Fehlt der Inhalt in der aktuellen Sprache, kann die Linie 6.5/6.6 auf die Standardsprache zurückfallen, während in der Linie 6.7 der Platzhalter unersetzt stehen bleibt. Dass getTranslation() die Fallback-Kette berücksichtigt, ist Verhalten des Shopware-Kerns und lässt sich im Quelltext des Plugins nicht belegen.

Dienstdefinitionen (services.xml), Migration, Tabellen, Platzhalter-Syntax, Twig-Filter und -Funktion, die Template-Dateien und die Admin-Texte stimmen in beiden Linien überein.