Wenn der Shopware-Kern eine Plugin-Route verdrängt
Ein Minor-Update kann eine Plugin-Route stilllegen, ohne dass irgendwo ein Fehler erscheint. Wir haben den Fall in zwei Runtimes nebeneinandergestellt und gemessen, welche Route gewinnt.
Ein Plugin läuft seit Monaten. Es installiert sauber, es ist aktiv, seine Konfiguration steht im Backend, und die Datei, die es ausliefern soll, ist im Shop erreichbar. Trotzdem stammt ihr Inhalt nicht mehr aus dem Plugin.
Das ist kein Einzelfall und kein Bug. Es ist die normale Arbeitsweise des Routers — und sie wird zum Problem, sobald der Kern einen Pfad belegt, den vorher ein Plugin hatte.
Der Aufbau
Wir betreiben für Kompatibilitätsprüfungen zwei Shopware-Runtimes parallel, mit identischem Pluginstand:
| Runtime | Version | Zweck |
|---|---|---|
pixup-sw66-compat | 6.6.10.6 | Nachweis, dass Erweiterungen auf der Vorgängerlinie weiterlaufen |
pixup-sw67-compat | 6.7.13.1 | Prüfung derselben Erweiterungen auf der aktuellen Linie |
In beiden ist eine Erweiterung installiert, die eine Route auf /robots.txt
registriert. Die Frage war nicht, ob sie installiert ist — das war sie in
beiden. Die Frage war, ob sie noch etwas ausliefert.
Die Messung
Ein einziger Befehl beantwortet das:
bin/console debug:router | grep robots
Shopware 6.6.10.6 — eine Route:
frontend.pixup.robotstxt GET /robots.txt
Shopware 6.7.13.1 — zwei Routen auf demselben Pfad:
frontend.robots.txt GET /robots.txt
frontend.pixup.robotstxt GET /robots.txt
Der Kern hat den Pfad übernommen. Beide Routen sind registriert, beide
akzeptieren GET, beide haben dasselbe Pfad-Regex {^/robots\.txt$}sDu.
Welche antwortet? Auch das lässt sich messen, statt es zu vermuten:
bin/console router:match /robots.txt --method=GET
[OK] Route "frontend.robots.txt" matches
Die Kernroute gewinnt. Die Pluginroute ist registriert, sichtbar, konfiguriert — und wird nie aufgerufen.
Warum das so ist
Symfony behandelt Routen als geordnete Liste und nimmt die erste, deren Pfad und Methode passen. Es gibt keinen Prioritätswert, den ein Plugin hochsetzen könnte, und es gibt keine Warnung bei doppelten Pfaden. Aus Sicht des Routers ist das kein Konflikt, sondern eine beantwortete Anfrage.
Entscheidend ist damit allein die Ladereihenfolge — und die Routendateien des Kerns werden vor denen der Plugins gelesen. Ein Plugin kann eine Kernroute auf demselben Pfad also nicht überstimmen, solange es nur eine weitere Route registriert.
Das ist der unangenehme Teil: Die Erweiterung verhält sich in jeder
sichtbaren Hinsicht korrekt. plugin:list zeigt sie als aktiv. Das Backend
zeigt ihre Einstellungen. Die URL liefert eine gültige Antwort mit Status 200.
Nur der Inhalt kommt von woanders. Es gibt keinen Log-Eintrag, keine
Health-Check-Warnung und keinen Deprecation-Hinweis, der darauf zeigt.
Woran man es merkt — und woran nicht
| Prüfung | Schlägt an? |
|---|---|
plugin:list zeigt das Plugin aktiv | nein, es ist aktiv |
| HTTP-Status der URL | nein, 200 |
| Log-Dateien | nein, kein Fehler |
| Backend-Konfiguration lässt sich speichern | nein, sie wird nur nicht mehr gelesen |
| Inhalt der Antwort mit der erwarteten Ausgabe vergleichen | ja |
debug:router, Pfad kommt doppelt vor | ja |
router:match <pfad> nennt eine fremde Route | ja |
Die drei unteren Zeilen sind der Grund, warum ein Kompatibilitätstest nicht bei „installiert und Seite lädt" aufhören darf. Ein Plugin gilt uns erst dann als lauffähig auf einer neuen Minor-Version, wenn seine Wirkung gemessen ist — nicht seine Anwesenheit.
Was Plugin-Entwickler daraus mitnehmen
Eigene Pfade wählen, die der Kern nicht braucht. Ein Plugin, das unter
einem eigenen Präfix arbeitet, gerät nie in diese Lage. Standardpfade wie
/robots.txt, /sitemap.xml oder /health sind Kandidaten dafür, in einer
kommenden Version im Kern aufzutauchen.
Beim Versionswechsel Pfade gegeneinander prüfen. debug:router vor und
nach dem Update, Ausgabe vergleichen, doppelte Pfade suchen. Das dauert eine
Minute und ist die einzige Prüfung, die dieses Muster zuverlässig findet.
Nicht auf einen Fehler warten. Diese Klasse von Regression meldet sich nicht. Sie fällt auf, wenn jemand den ausgelieferten Inhalt anschaut — im schlechtesten Fall Monate später, wenn eine Suchmaschine sich anders verhält als erwartet.
Was Shopbetreiber daraus mitnehmen
Nach einem Minor-Update ist die Frage nicht „läuft der Shop", sondern „tun die Erweiterungen noch, wofür sie gekauft wurden". Der Unterschied klingt klein und ist er nicht: ein Shop kann vollständig funktionieren, während drei Erweiterungen still nichts mehr beitragen.
Eine kurze Prüfliste nach jedem Minor-Update:
- Welche Erweiterungen liefern eine Datei oder Route aus? Deren Ausgabe direkt abrufen und mit dem Erwarteten vergleichen.
debug:routerauf doppelte Pfade durchsehen.- Erweiterungen, die Felder am Produkt schreiben, gegen die aktuelle Definition prüfen — Shopware macht Felder zwischen Versionen auch schreibgeschützt. Wie das aussieht, steht in Produktdaten übersetzen, ohne Daten zu verlieren.
Warum wir das aufgeschrieben haben
Wir entwickeln eigene Shopware-Erweiterungen und pflegen sie über Versionswechsel hinweg — die vier öffentlich verfügbaren stehen unter Shopware Plugins. Dieser Befund stammt aus genau dieser Arbeit: aus der Kompatibilitätsprüfung, nicht aus einem Kundenvorfall.
Wenn Sie eine Erweiterung betreiben, die auf einem Standardpfad arbeitet, ist der Befehl oben eine Minute gut investierter Zeit. Wenn Sie unsicher sind, welche Ihrer Erweiterungen betroffen sein könnten, hilft ein Blick von außen: Shopware-Support beschreibt, wie wir solche Prüfungen durchführen.
Häufige Fragen
- Warum meldet Shopware keinen Fehler, wenn zwei Routen denselben Pfad haben?
- Weil es aus Sicht des Routers kein Fehler ist. Symfony sammelt alle Routen in einer geordneten Liste und nimmt die erste, die passt. Doppelte Pfade sind erlaubt; die späteren sind schlicht unerreichbar. Es gibt keine Kollisionsprüfung, die anschlägt.
- Hilft es, dem Plugin eine höhere Priorität zu geben?
- Es gibt keinen Prioritätswert für Routen in Symfony. Was zählt, ist die Reihenfolge, in der die Routendateien geladen werden — und Kernrouten werden vor Pluginrouten geladen. Ein Plugin kann sich nicht davorschieben, ohne in den Ladevorgang einzugreifen.
- Wie finde ich betroffene Routen im eigenen Shop?
- bin/console debug:router listet alle Routen mit Pfad. Wenn derselbe Pfad zweimal auftaucht, ist eine davon tot. bin/console router:match <pfad> sagt, welche gewinnt.
- Betrifft das nur /robots.txt?
- Nein. Der Pfad ist nur der Fall, an dem wir es gemessen haben. Das Muster gilt für jede Route, die ein Plugin auf einem Pfad registriert, den der Kern später selbst belegt — und Shopware ergänzt in Minor-Releases regelmäßig Storefront-Routen.
