Zum Inhalt springen

Symfony-Entwicklerhandbuch

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.

SchichtVerantwortlichZuständigkeitGehört nicht hierher
ControllerAnwendungAutorisiert die Anfrage, sammelt die Eingabe und gibt PdfResponse zurück.Gemeinsam genutztes PDF-Layout für mehrere Anwendungsfälle.
AnwendungsserviceAnwendungLädt die Domänendaten und wählt einen Builder aus.Logik des Symfony-Container-Compilers.
Builder-ServiceAnwendungImplementiert PdfBuilderInterface für synchrone oder in die Warteschlange gestellte Dokumenterstellung.Request-Objekte, Entity-Manager oder nicht serialisierbarer Kontext.
Symfony-Bundlenextpdf/symfonyRegistriert Services, den Konfigurationsbaum, den optionalen Erweiterungs-Pass, Response-Helper und Messenger-DTOs.Mandantenspezifische Speicherrichtlinie.
Kern-Enginenextpdf/nextpdfErstellt und serialisiert das Dokument.Symfony-Response- oder Messenger-Verhalten.
PhaseVerhaltenEntwickleraktion
Bundle-BootNextPdfBundle::build() registriert die optionale Erweiterungserkennung.Lassen Sie Symfony das Bundle entdecken oder registrieren Sie es in bundles.php.
KonfigurationsladevorgangNextPdfExtension::load() verarbeitet die nextpdf:-Konfiguration und lädt die Servicedefinitionen.Halten Sie die Konfiguration explizit und umgebungsbewusst.
Factory-NutzungPdfFactory::create() liefert ein frisch konfiguriertes Dokument.Speichern Sie keine Dokumente in Services.
Controller-AusgabePdfResponse verwandelt ein fertiges Dokument in eine Response.Nutzen Sie den Helper, statt die Header manuell zusammenzusetzen.
Messenger-DispatchGeneratePdfMessage enthält Builder-Klasse, Ausgabepfad und serialisierbaren Kontext.Halten Sie den Kontext klein und mit skalaren Werten kompatibel.
NachrichtenverarbeitungGeneratePdfHandler löst den Builder aus einem Service-Locator auf und speichert das Dokument.Gestalten Sie Builder deterministisch und idempotent.
PfadZweck
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;
}
}
<?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.

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.

ErweiterungspunktEinsatzbereichEinschränkung
PdfFactory-Service-DekorationAnwendungsstandards anwenden, bevor Dokumente die Controller erreichen.Muss die Semantik des frischen Dokuments bewahren.
PdfBuilderInterfaceDefinition von in die Warteschlange gestellten oder wiederverwendbaren Dokument-Buildern.Muss ein Document zurückgeben.
OptionalExtensionPassAktivieren optionaler Artisan- oder Premium-Funktionen zur Compile-Zeit.Die Verfügbarkeit hängt vom Container-Compile-Zustand ab, nicht vom Request-Zustand.
Symfony-KonfigurationsbaumStandards, PDF/A, Renderer-Einstellungen, Signatur, TSA, Messenger.Eine ungültige Konfiguration sollte während des Container-Builds fehlschlagen.
GeneratePdfHandler-Service-VerdrahtungEinschränken, welche Builder für in die Warteschlange gestellte Nachrichten erreichbar sind.Der Service-Locator sollte nur freigegebene Builder-Services bereitstellen.
  1. Fügen Sie einen Builder-Service mit deterministischer Eingabe hinzu.
  2. Verwenden Sie PdfFactory::create() in einem Controller oder Service.
  3. Fügen Sie einen Response-Test für Dateiname, Content-Type und Header hinzu.
  4. Registrieren Sie den Builder für Messenger, wenn dasselbe Dokument asynchron generiert werden muss.
  5. Fügen Sie Tests für ungültige Nachrichten hinzu, die Klassennamen, Ausgabepfad und Kontextform abdecken.
  6. Fügen Sie einen Container-Kompilierungstest mit minimaler und produktiver Konfiguration hinzu.
  7. Messen Sie Renderzeit und Speicherverbrauch unter denselben PHP-Einstellungen wie in der Produktion.
FehlerWo der Fehler behandelt werden sollteEmpfohlene Reaktion
Ungültige KonfigurationContainer-Kompilierung.Lassen Sie das Deployment fehlschlagen, bevor Traffic die Anwendung erreicht.
Fehlender Builder-ServiceMessenger-Handler-Tests und Service-Tags.Lassen Sie die Nachricht fehlschlagen und alarmieren Sie das zuständige Team.
Unsicherer AusgabepfadNachrichten-Konstruktor und Speicherrichtlinie.Lehnen Sie vor dem Dispatch ab; behalten Sie die Handler-Validierung als Verteidigung in der Tiefe bei.
Optionale Erweiterung nicht verfügbarCompiler-Pass und Factory-Verhalten.Deaktivieren Sie die optionale Funktion oder machen Sie die Installation explizit.
Service-Konvertierung oder Render-FehlerBuilder-Grenze.Lassen Sie den Vorgang geschlossen fehlschlagen, sofern der Anwendungsfall keinen dokumentierten Fallback hat.
AspektStandardWann überschreiben
Lebensdauer der FactoryContainer-Service.Behalten Sie dies bei; die Factory ist sicher, weil sie Dokumente erzeugt.
Lebensdauer des DokumentsEine Arbeitseinheit.Teilen Sie es niemals über Requests oder Nachrichten hinweg.
Validierung des AusgabepfadsNachrichten-Konstruktor und Handler.Fügen Sie Mandanten- oder Speicher-Root-Einschränkungen im Anwendungscode hinzu.
Response-Dateinamedocument.pdf.Überschreiben Sie ihn mit bereinigten Geschäftskennungen.
Messenger-Transportasync.Nutzen Sie einen dedizierten Transport, wenn die PDF-Arbeit aufwendig ist.
  • 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.