NextPDF Symfony-Schnellstart
Auf einen Blick
Abschnitt betitelt „Auf einen Blick“Injizieren Sie PdfFactory, erstellen Sie ein Document und geben Sie es über PdfResponse zurück. Um ein PDF im Hintergrund zu erzeugen, senden Sie eine GeneratePdfMessage an einen Messenger-Transport.
Schritt 1 – Ein PDF in einem Controller erzeugen
Abschnitt betitelt „Schritt 1 – Ein PDF in einem Controller erzeugen“Injizieren Sie NextPDF\Symfony\Service\PdfFactory. Die Methode create() liefert ein neues NextPDF\Core\Document zurück. Die konfigurierten Standardwerte sind bereits für Sie gesetzt: Ersteller, Autor und Sprache. Geben Sie dieses Dokument über NextPDF\Symfony\Http\PdfResponse zurück.
<?php
declare(strict_types=1);
namespace App\Controller;
use NextPDF\Symfony\Http\PdfResponse;use NextPDF\Symfony\Service\PdfFactory;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Routing\Attribute\Route;
final class InvoiceController{ #[Route('/invoice/{number}', name: 'invoice_pdf')] public function download(PdfFactory $pdf, string $number): Response { $doc = $pdf->create(); $doc->addPage(); $doc->cell(0, 10, "Invoice #{$number}", newLine: true); $doc->cell(0, 10, 'Thank you for your business.');
return PdfResponse::download($doc, "invoice-{$number}.pdf"); }}PdfResponse::download() liefert eine Symfony\Component\HttpFoundation\Response zurück. Sie setzt Content-Type: application/pdf, eine attachment-Disposition, eine Content-Length sowie die vom Bundle fest vorgegebenen Sicherheits-Header. Symfony dokumentiert die kanonische Response-Klasse und ihr Header-Modell (https://symfony.com/doc/current/components/http_foundation.html).
Schritt 2 – Ein PDF inline anzeigen
Abschnitt betitelt „Schritt 2 – Ein PDF inline anzeigen“Damit der Browser das PDF anzeigt, anstatt es herunterzuladen, verwenden Sie inline():
return PdfResponse::inline($doc, 'preview.pdf');Die Disposition wird auf inline gesetzt. Alle anderen Header bleiben unverändert.
Schritt 3 – Ein großes PDF streamen
Abschnitt betitelt „Schritt 3 – Ein großes PDF streamen“Bei großen Dokumenten geben die Streaming-Varianten das PDF in 64-KB-Blöcken aus. Dadurch sinkt der maximale Speicherverbrauch. Sie liefern eine Symfony\Component\HttpFoundation\StreamedResponse zurück und setzen kein Content-Length.
return PdfResponse::streamDownload($doc, 'annual-report.pdf');streamInline() ist das entsprechende Inline-Äquivalent. Symfony dokumentiert den Callback-Vertrag von StreamedResponse, also ein void-Callable, das die Ausgabe leert (https://symfony.com/doc/current/components/http_foundation.html).
Schritt 4 – Ein PDF asynchron erzeugen
Abschnitt betitelt „Schritt 4 – Ein PDF asynchron erzeugen“Wenn symfony/messenger installiert ist, können Sie die Erzeugung aus dem Request-Thread herauslösen.
4a – Einen Builder implementieren
Abschnitt betitelt „4a – Einen Builder implementieren“Implementieren Sie NextPDF\Symfony\Message\PdfBuilderInterface. Der Handler übergibt Ihnen ein neues, vorkonfiguriertes Document. Zusätzlich übergibt er den serialisierbaren Kontext aus der Nachricht.
<?php
declare(strict_types=1);
namespace App\Pdf;
use NextPDF\Core\Document;use NextPDF\Symfony\Message\PdfBuilderInterface;
final class InvoicePdfBuilder implements PdfBuilderInterface{ public function build(Document $document, array $context): Document { $document->addPage(); $document->setFont('dejavusans', '', 12); $document->cell(0, 10, 'Invoice #' . $context['invoice_id']);
return $document; }}4b – Den Builder im Locator registrieren
Abschnitt betitelt „4b – Den Builder im Locator registrieren“Der Handler löst Builder über einen PSR-11-Service-Locator auf, dessen Schlüssel Klassennamen sind. Dadurch sind nur registrierte Builder erreichbar. Fügen Sie den Builder in config/services.yaml einem Locator hinzu:
services: App\Pdf\InvoicePdfBuilder: ~
nextpdf.pdf_builder_locator: class: Symfony\Component\DependencyInjection\ServiceLocator arguments: - 'App\Pdf\InvoicePdfBuilder': '@App\Pdf\InvoicePdfBuilder' tags: ['container.service_locator']
NextPDF\Symfony\Message\GeneratePdfHandler: arguments: $builderLocator: '@nextpdf.pdf_builder_locator'Der Handler fordert den Builder über dessen Klassen-String-ID beim Locator an. Eine PSR-11-Container-Kennung ist eine Zeichenkette, die einen Eintrag eindeutig identifiziert (PSR-11 §1.1.2).
4c – Die Nachricht versenden
Abschnitt betitelt „4c – Die Nachricht versenden“Injizieren Sie Symfony\Component\Messenger\MessageBusInterface und versenden Sie anschließend die Nachricht:
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Pdf\InvoicePdfBuilder;use NextPDF\Symfony\Message\GeneratePdfMessage;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\Messenger\MessageBusInterface;use Symfony\Component\Routing\Attribute\Route;
final class ReportController{ #[Route('/invoice/{id}/queue', name: 'invoice_queue')] public function queue(MessageBusInterface $bus, int $id): Response { $bus->dispatch(new GeneratePdfMessage( builderClass: InvoicePdfBuilder::class, outputPath: '/var/storage/invoices/' . $id . '.pdf', builderContext: ['invoice_id' => $id], ));
return new Response('PDF generation queued.', 202); }}GeneratePdfMessage ist ein readonly-DTO. Sein Konstruktor weist leere Ausgabepfade, Ausgabepfade ohne .pdf-Endung, Path-Traversal-Segmente, Stream-Wrapper-Schemata und Null-Bytes zurück. Außerdem verlangt er, dass builderClass ein syntaktisch gültiger Klassenname ist. Der Handler validiert den Ausgabepfad zur Ausführungszeit erneut, bevor er schreibt. Dadurch wird ein Pfad weiterhin zurückgewiesen, wenn er beim Versenden sicher war, beim Verarbeiten aber unsicher ist. Das Attribut #[AsMessageHandler] und der Dispatch-Vertrag von MessageBusInterface folgen dem Standardmodell von Symfony Messenger (https://symfony.com/doc/current/messenger.html).
4d – Die Nachricht routen und einen Worker ausführen
Abschnitt betitelt „4d – Die Nachricht routen und einen Worker ausführen“Routen Sie die Nachricht in config/packages/messenger.yaml zu einem Transport:
framework: messenger: transports: async: '%env(MESSENGER_TRANSPORT_DSN)%' routing: NextPDF\Symfony\Message\GeneratePdfMessage: asyncFühren Sie anschließend einen Worker aus:
php bin/console messenger:consume asyncÜberprüfen, ob es funktioniert
Abschnitt betitelt „Überprüfen, ob es funktioniert“php bin/console debug:container --tag=container.service_locatorphp bin/console messenger:consume async --limit=1 -vvDer erste Befehl bestätigt, dass der Builder-Locator registriert ist. Der zweite Befehl verarbeitet eine einzelne Nachricht aus der Warteschlange und gibt den Fortschritt des Handlers aus.
Nächste Schritte
Abschnitt betitelt „Nächste Schritte“- /integrations/symfony/configuration/ – Standardwerte, Schriftarten und den Dokument-Service anpassen.
- /integrations/symfony/production-usage/ – Worker-Sicherheit und Streaming unter Last.
- /integrations/symfony/troubleshooting/ – häufige Boot- und Laufzeitprobleme.
Konformität
Abschnitt betitelt „Konformität“Jede auf dieser Seite getroffene normative Aussage ist mit einer vollständigen 64-stelligen Hex-reference_id aus dem gegateten SDO-Korpus verankert. Die Provenance (Korpus-Manifest, Retrieval-Transport) ist in _sidecars/rag-citations.yaml dokumentiert.
| Spec | Klausel | reference_id | Aussage |
|---|---|---|---|
| PSR-11 | psr_11_container#1.1.2.p4 | Identifier-Vertrag von Container-has()/get() |
Siehe auch
Abschnitt betitelt „Siehe auch“- /integrations/symfony/overview/ – Funktionsübersicht.
- /integrations/symfony/install/ – Installation und Registrierung.
- /integrations/symfony/integration/ – End-to-End-Referenz zur Verdrahtung.