Symfony-Entwicklerhandbuch
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Das Symfony-Paket ist service-first ausgelegt. Injizieren Sie PdfFactory, rufen Sie create() für jedes Dokument auf und nutzen Sie Messenger-Builder für die asynchrone Generierung. Die Factory kann als Container-Service registriert sein, weil jeder Aufruf ein frisches Dokument liefert.
Nutzen Sie dieses Handbuch, wenn Sie Controller, Services, Messenger-Handler oder Erweiterungspunkte auf Bundle-Ebene rund um nextpdf/symfony entwerfen.
Architekturgrenze
Abschnitt betitelt „Architekturgrenze“| Schicht | Verantwortlich | Zuständigkeit | Gehört nicht hierher |
|---|---|---|---|
| Controller | Anwendung | Autorisiert die Anfrage, sammelt die Eingabe und gibt PdfResponse zurück. | Gemeinsam genutztes PDF-Layout für mehrere Anwendungsfälle. |
| Anwendungsservice | Anwendung | Lädt die Domänendaten und wählt einen Builder aus. | Logik des Symfony-Container-Compilers. |
| Builder-Service | Anwendung | Implementiert PdfBuilderInterface für synchrone oder in die Warteschlange gestellte Dokumenterstellung. | Request-Objekte, Entity-Manager oder nicht serialisierbarer Kontext. |
| Symfony-Bundle | nextpdf/symfony | Registriert Services, den Konfigurationsbaum, den optionalen Erweiterungs-Pass, Response-Helper und Messenger-DTOs. | Mandantenspezifische Speicherrichtlinie. |
| Kern-Engine | nextpdf/nextpdf | Erstellt und serialisiert das Dokument. | Symfony-Response- oder Messenger-Verhalten. |
Laufzeit-Lebenszyklus
Abschnitt betitelt „Laufzeit-Lebenszyklus“| Phase | Verhalten | Entwickleraktion |
|---|---|---|
| Bundle-Boot | NextPdfBundle::build() registriert die optionale Erweiterungserkennung. | Lassen Sie Symfony das Bundle entdecken oder registrieren Sie es in bundles.php. |
| Konfigurationsladevorgang | NextPdfExtension::load() verarbeitet die nextpdf:-Konfiguration und lädt die Servicedefinitionen. | Halten Sie die Konfiguration explizit und umgebungsbewusst. |
| Factory-Nutzung | PdfFactory::create() liefert ein frisch konfiguriertes Dokument. | Speichern Sie keine Dokumente in Services. |
| Controller-Ausgabe | PdfResponse verwandelt ein fertiges Dokument in eine Response. | Nutzen Sie den Helper, statt die Header manuell zusammenzusetzen. |
| Messenger-Dispatch | GeneratePdfMessage enthält Builder-Klasse, Ausgabepfad und serialisierbaren Kontext. | Halten Sie den Kontext klein und mit skalaren Werten kompatibel. |
| Nachrichtenverarbeitung | GeneratePdfHandler löst den Builder aus einem Service-Locator auf und speichert das Dokument. | Gestalten Sie Builder deterministisch und idempotent. |
Empfohlene Anwendungsstruktur
Abschnitt betitelt „Empfohlene Anwendungsstruktur“| Pfad | Zweck |
|---|---|
src/Pdf/Builder/* | Services, die PdfBuilderInterface implementieren. |
src/Pdf/Data/* | Kleine DTOs oder Arrays, die als Builder-Kontext dienen. |
src/Pdf/Storage/* | Auswahl des Speicher-Roots und Richtlinie für den Ausgabedateinamen. |
src/Controller/* | Synchrone Response-Einstiegspunkte. |
tests/Pdf/* | Tests für Builder, Response, Messenger und Konfiguration. |
Bevorzugen Sie Builder-Services gegenüber statischen Helper-Funktionen. Sie lassen sich unkompliziert taggen, dekorieren, testen und über Messenger nutzen.
<?php
namespace App\Pdf\Builder;
use NextPDF\Core\Document;use NextPDF\Symfony\Message\PdfBuilderInterface;
final readonly class InvoicePdfBuilder implements PdfBuilderInterface{ public function build(Document $document, array $context): Document { $document->setTitle((string) $context['title']) ->addPage() ->writeHtml((string) $context['html']);
return $document; }}Muster für synchrone Responses
Abschnitt betitelt „Muster für synchrone Responses“<?php
namespace App\Controller;
use App\Pdf\Builder\InvoicePdfBuilder;use NextPDF\Symfony\Http\PdfResponse;use NextPDF\Symfony\Service\PdfFactory;
final readonly class InvoiceController{ public function __invoke( PdfFactory $factory, InvoicePdfBuilder $builder, ) { $document = $builder->build($factory->create(), [ 'title' => 'Invoice 1234', 'html' => '<h1>Invoice 1234</h1>', ]);
return PdfResponse::download($document, 'invoice-1234.pdf'); }}Halten Sie den Controller-Kontext klein. Wenn ein Builder viele Domänenobjekte benötigt, verlagern Sie die Orchestrierung in einen Anwendungsservice und übergeben Sie dem Builder ein DTO oder ein normalisiertes Array.
Messenger-Muster
Abschnitt betitelt „Messenger-Muster“GeneratePdfMessage validiert die Builder-Klasse und den Ausgabepfad vor dem Dispatch. Der Handler validiert den Pfad zur Laufzeit erneut.
<?php
use App\Pdf\Builder\InvoicePdfBuilder;use NextPDF\Symfony\Message\GeneratePdfMessage;
$bus->dispatch(new GeneratePdfMessage( builderClass: InvoicePdfBuilder::class, outputPath: $projectDir . '/var/pdfs/invoice-1234.pdf', builderContext: [ 'title' => 'Invoice 1234', 'html' => '<h1>Invoice 1234</h1>', ],));Legen Sie keine Doctrine-Entities, offenen Streams, Closures, Request-Objekte oder Service-Objekte in builderContext ab.
Erweiterungspunkte
Abschnitt betitelt „Erweiterungspunkte“| Erweiterungspunkt | Einsatzbereich | Einschränkung |
|---|---|---|
PdfFactory-Service-Dekoration | Anwendungsstandards anwenden, bevor Dokumente die Controller erreichen. | Muss die Semantik des frischen Dokuments bewahren. |
PdfBuilderInterface | Definition von in die Warteschlange gestellten oder wiederverwendbaren Dokument-Buildern. | Muss ein Document zurückgeben. |
OptionalExtensionPass | Aktivieren optionaler Artisan- oder Premium-Funktionen zur Compile-Zeit. | Die Verfügbarkeit hängt vom Container-Compile-Zustand ab, nicht vom Request-Zustand. |
| Symfony-Konfigurationsbaum | Standards, PDF/A, Renderer-Einstellungen, Signatur, TSA, Messenger. | Eine ungültige Konfiguration sollte während des Container-Builds fehlschlagen. |
GeneratePdfHandler-Service-Verdrahtung | Einschränken, welche Builder für in die Warteschlange gestellte Nachrichten erreichbar sind. | Der Service-Locator sollte nur freigegebene Builder-Services bereitstellen. |
Entwicklungs-Workflow
Abschnitt betitelt „Entwicklungs-Workflow“- Fügen Sie einen Builder-Service mit deterministischer Eingabe hinzu.
- Verwenden Sie
PdfFactory::create()in einem Controller oder Service. - Fügen Sie einen Response-Test für Dateiname, Content-Type und Header hinzu.
- Registrieren Sie den Builder für Messenger, wenn dasselbe Dokument asynchron generiert werden muss.
- Fügen Sie Tests für ungültige Nachrichten hinzu, die Klassennamen, Ausgabepfad und Kontextform abdecken.
- Fügen Sie einen Container-Kompilierungstest mit minimaler und produktiver Konfiguration hinzu.
- Messen Sie Renderzeit und Speicherverbrauch unter denselben PHP-Einstellungen wie in der Produktion.
Fehlerbehandlung
Abschnitt betitelt „Fehlerbehandlung“| Fehler | Wo der Fehler behandelt werden sollte | Empfohlene Reaktion |
|---|---|---|
| Ungültige Konfiguration | Container-Kompilierung. | Lassen Sie das Deployment fehlschlagen, bevor Traffic die Anwendung erreicht. |
| Fehlender Builder-Service | Messenger-Handler-Tests und Service-Tags. | Lassen Sie die Nachricht fehlschlagen und alarmieren Sie das zuständige Team. |
| Unsicherer Ausgabepfad | Nachrichten-Konstruktor und Speicherrichtlinie. | Lehnen Sie vor dem Dispatch ab; behalten Sie die Handler-Validierung als Verteidigung in der Tiefe bei. |
| Optionale Erweiterung nicht verfügbar | Compiler-Pass und Factory-Verhalten. | Deaktivieren Sie die optionale Funktion oder machen Sie die Installation explizit. |
| Service-Konvertierung oder Render-Fehler | Builder-Grenze. | Lassen Sie den Vorgang geschlossen fehlschlagen, sofern der Anwendungsfall keinen dokumentierten Fallback hat. |
Sichere Standards
Abschnitt betitelt „Sichere Standards“| Aspekt | Standard | Wann überschreiben |
|---|---|---|
| Lebensdauer der Factory | Container-Service. | Behalten Sie dies bei; die Factory ist sicher, weil sie Dokumente erzeugt. |
| Lebensdauer des Dokuments | Eine Arbeitseinheit. | Teilen Sie es niemals über Requests oder Nachrichten hinweg. |
| Validierung des Ausgabepfads | Nachrichten-Konstruktor und Handler. | Fügen Sie Mandanten- oder Speicher-Root-Einschränkungen im Anwendungscode hinzu. |
| Response-Dateiname | document.pdf. | Überschreiben Sie ihn mit bereinigten Geschäftskennungen. |
| Messenger-Transport | async. | Nutzen Sie einen dedizierten Transport, wenn die PDF-Arbeit aufwendig ist. |
Test-Checkliste
Abschnitt betitelt „Test-Checkliste“- Container-Tests kompilieren das Bundle mit minimaler und produktiver Konfiguration.
- Response-Tests prüfen Security-Header und die Behandlung des Dateinamens.
- Messenger-Tests prüfen, dass ungültige Pfade und ungültige Builder-Klassennamen vor dem Dispatch fehlschlagen.
- Handler-Tests nutzen einen echten Builder-Service und ein temporäres Ausgabeverzeichnis.
- Builder-Tests rendern ein repräsentatives Dokument und speichern es mit produktionsähnlichen Dateisystemberechtigungen.
- Optionale Erweiterungstests decken die Fälle ab, dass Artisan nicht verfügbar ist, Premium nicht verfügbar ist und wie sich ein konfiguriertes PDF/A-Profil verhält.