Markus Michalski FAQ

Support Form: Technische Details

Support Form für Sylius - Ablauf einer Anfrage als Diagramm, Dual-Mode im Überblick, Plugin-Struktur, die sechs Tabellen, Migrationen und Details der Admin-Oberfläche

English Version

Zurück zur Übersicht

Support Form: Technische Details

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

Ablauf einer Anfrage

Storefront und Shop API laufen in dieselbe Verarbeitung. Dort wird zuerst das Event ausgelöst, und nur wenn kein Listener ablehnt, geht die Anfrage weiter.

graph TD
    A["Kunde: POST /support"] --> B{"Formular gültig?"}
    H["Client: POST /shop/support-requests"] --> I["Entity-Validierung"]
    I --> J["Betreff gegen Auswahlliste prüfen"]
    J --> K["Antworten mit Formularregeln prüfen"]
    B -->|Ja| M["Antworten und E-Mail-Adresse ableiten"]
    K --> M
    M --> N["Betreff-Code in Bezeichnung auflösen"]
    N --> O["Event PRE_PERSIST"]
    O --> Q{"Von Listener abgelehnt?"}
    Q -->|Ja| U["Storefront: Fehlermeldung, API: 422"]
    Q -->|Nein| R["Anfrage speichern"]
    R --> S["Mail an den Betreiber"]
    R --> T["Bestätigung an den Kunden"]
    S --> V["Storefront: Erfolgsmeldung, API: 201"]
    T --> V

Die Verarbeitung (SupportRequestSubmissionHandler) ist der einzige Ort, an dem gespeichert und benachrichtigt wird. Controller und API-Prozessor rufen sie nur auf. Jede der beiden Mails hat einen eigenen Fehlerschutz: Scheitert eine, ist die Anfrage trotzdem gespeichert, und die andere geht raus. Protokolliert werden nur Exception-Klasse und Code, nie die Meldung, weil sie personenbezogene Daten enthalten kann.

Dual-Mode im Überblick

Fähigkeit Storefront Shop API
Anfrage absenden GET/POST /support POST /shop/support-requests
Zusatzfelder Im Formular als field_<ID> GET /shop/support-form-fields
Antworten Eingabefelder field_<ID> Objekt answers, Schlüssel ist die ID des Feldes
Betreff-Auswahl Feld „Betreff“ im Formular GET /shop/support-form-subject-choices
Bestätigung an den Kunden Wenn die Anfrage eine Adresse hat Wenn answers eine beantwortete E-Mail enthält
Anfragen ansehen /admin/support-requests GET /admin/support-requests

Plugin-Struktur

src/
├── Api/                  # Shop-API-Prozessor und -Provider, Prüfung der Antworten, Betreff-Auswahl als DTO
├── Command/              # SetupCommand, PurgeSupportRequestsCommand
├── Controller/           # SupportRequestController (Storefront)
├── DependencyInjection/  # Bundle-Erweiterung (leere Konfiguration)
├── Entity/               # SupportRequest, SupportFormField (+ Übersetzung), SupportFormChannelConfiguration, Enums
├── Event/                # SupportRequestEvents, SupportRequestPrePersistEvent
├── Factory/              # SupportFormFieldFactory
├── Form/Type/            # SupportRequestType und die Admin-Formulare
├── Handler/              # SupportRequestSubmissionHandler
├── Mailer/               # SupportRequestMailer, Emails
├── Menu/                 # Admin-Sidebar-Eintrag in der Gruppe „MMKreativ Plugins“
├── Migrations/           # Drei Doctrine-Migrationen
├── Repository/           # Repositories der drei Ressourcen
├── Resolver/             # Betreff-Auswahl, Antwort-Sammler, Datenschutz-Link
└── Twig/                 # PluginVersionExtension
config/
├── grids/                # Drei Admin-Grids
├── routes/               # admin.yaml, shop.yaml
├── twig_hooks/           # admin.yaml, shop.yaml
└── mailer.yaml           # Zwei E-Mail-Templates
templates/
├── admin/                # Titelzeilen und Formulare, Detailansicht
├── emails/               # Benachrichtigung und Bestätigung
└── shop/                 # Formular und Footer-Link
translations/             # messages, validators, flashes in de und en

Tabellen und Migrationen

Das Plugin legt sechs Tabellen an.

graph LR
    A["support_request"] -->|"channel_id, SET NULL"| C["sylius_channel"]
    B["support_form_channel_configuration"] -->|"channel_id, CASCADE"| C
    B --- D["configuration_product"]
    B --- E["configuration_taxon"]
    F["support_form_field"] --- G["support_form_field_translation"]
Tabelle Inhalt
mmd_sylius_support_form_support_request Eingegangene Anfragen: created_at, email, subject, consent, channel_id, field_values
mmd_sylius_support_form_field Zusatzfelder: field_type, required, position, Grenzwerte, select_options
mmd_sylius_support_form_field_translation Bezeichnung und Platzhalter je Sprache
mmd_sylius_support_form_channel_configuration Eine Zeile pro Channel: subject_mode, recipient_email, privacy_policy_page
mmd_sylius_support_form_channel_configuration_product Zugeordnete Produkte
mmd_sylius_support_form_channel_configuration_taxon Zugeordnete Kategorien

Die Antworten auf die Zusatzfelder liegen als JSON-Liste aus label und value in der Spalte field_values der Anfrage und nicht in einer eigenen Tabelle. Das Plugin liest sie nie einzeln, sondern immer gemeinsam mit der Anfrage. Weil jede Antwort ihre Bezeichnung mitbringt, bleibt sie lesbar, wenn du das Feld später änderst oder löschst.

Die Spalte channel_id einer Anfrage wird beim Löschen eines Channels auf NULL gesetzt, die Konfiguration des Channels dagegen mit gelöscht.

Migration Änderung
Version20260928095114 Legt alle sechs Tabellen an
Version20260929120000 Ergänzt recipient_email an der Channel-Konfiguration
Version20260929140000 Ergänzt privacy_policy_page an der Channel-Konfiguration

Admin-Details