Avvio rapido a NextPDF per Symfony
In breve
Sezione intitolata “In breve”Iniettare PdfFactory, costruire un Document e restituirlo con PdfResponse. Per generare un PDF in background, inviare un GeneratePdfMessage a un trasporto Messenger.
Passaggio 1 — Generare un PDF in un controller
Sezione intitolata “Passaggio 1 — Generare un PDF in un controller”Iniettare NextPDF\Symfony\Service\PdfFactory: il relativo metodo create() restituisce un nuovo NextPDF\Core\Document. I valori predefiniti configurati, cioè creatore, autore e lingua, vengono applicati automaticamente. Restituire tale documento con NextPDF\Symfony\Http\PdfResponse.
<?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() restituisce una Symfony\Component\HttpFoundation\Response. Imposta Content-Type: application/pdf, una disposizione attachment, un Content-Length e le intestazioni di sicurezza fisse del bundle. Symfony documenta la classe canonica Response e il relativo modello di intestazioni (https://symfony.com/doc/current/components/http_foundation.html).
Passaggio 2 — Visualizzare un PDF inline
Sezione intitolata “Passaggio 2 — Visualizzare un PDF inline”Per consentire al browser di visualizzare il PDF invece di scaricarlo, utilizzare inline():
return PdfResponse::inline($doc, 'preview.pdf');La disposizione passa a inline. Tutte le altre intestazioni rimangono invariate.
Passaggio 3 — Trasmettere in streaming un PDF di grandi dimensioni
Sezione intitolata “Passaggio 3 — Trasmettere in streaming un PDF di grandi dimensioni”Per i documenti di grandi dimensioni, le varianti in streaming emettono il PDF in blocchi da 64 KB. Questo riduce il picco di memoria. Restituiscono una Symfony\Component\HttpFoundation\StreamedResponse e omettono Content-Length.
return PdfResponse::streamDownload($doc, 'annual-report.pdf');streamInline() è l’equivalente inline. Symfony documenta il contratto di callback StreamedResponse, cioè un callable void che effettua il flush dell’output (https://symfony.com/doc/current/components/http_foundation.html).
Passaggio 4 — Generare un PDF in modo asincrono
Sezione intitolata “Passaggio 4 — Generare un PDF in modo asincrono”Quando symfony/messenger è installato, è possibile spostare la generazione fuori dal thread della richiesta.
4a — Implementare un builder
Sezione intitolata “4a — Implementare un builder”Implementare NextPDF\Symfony\Message\PdfBuilderInterface. L’handler passa un Document nuovo e preconfigurato. Passa anche il contesto serializzabile contenuto nel messaggio.
<?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 — Registrare il builder nel locator
Sezione intitolata “4b — Registrare il builder nel locator”L’handler risolve i builder da un service locator PSR-11 indicizzato per nome di classe. Di conseguenza, solo i builder registrati sono risolvibili. Aggiungere il builder a un locator in config/services.yaml:
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'L’handler richiede al locator il builder tramite il relativo id class-string. Un identificatore di container PSR-11 è una stringa che identifica in modo univoco una voce (PSR-11 §1.1.2).
4c — Inviare il messaggio
Sezione intitolata “4c — Inviare il messaggio”Iniettare Symfony\Component\Messenger\MessageBusInterface e inviare il messaggio:
<?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 è un DTO readonly. Il relativo costruttore rifiuta percorsi di output vuoti o non .pdf, segmenti di path traversal, schemi degli stream wrapper e byte null. Richiede inoltre che builderClass sia un nome di classe sintatticamente valido. L’handler convalida di nuovo il percorso di output in fase di esecuzione, prima di scrivere. Pertanto, un percorso sicuro al momento dell’invio ma non sicuro al momento del consumo viene comunque rifiutato. L’attributo #[AsMessageHandler] e il contratto di invio MessageBusInterface seguono il modello standard di Symfony Messenger (https://symfony.com/doc/current/messenger.html).
4d — Instradare il messaggio ed eseguire un worker
Sezione intitolata “4d — Instradare il messaggio ed eseguire un worker”In config/packages/messenger.yaml, instradare il messaggio verso un trasporto:
framework: messenger: transports: async: '%env(MESSENGER_TRANSPORT_DSN)%' routing: NextPDF\Symfony\Message\GeneratePdfMessage: asyncQuindi eseguire un worker:
php bin/console messenger:consume asyncVerificare il funzionamento
Sezione intitolata “Verificare il funzionamento”php bin/console debug:container --tag=container.service_locatorphp bin/console messenger:consume async --limit=1 -vvIl primo comando conferma che il locator del builder è registrato. Il secondo consuma un singolo messaggio accodato e stampa lo stato di avanzamento dell’handler.
Passaggi successivi
Sezione intitolata “Passaggi successivi”- /integrations/symfony/configuration/ — ottimizzare i valori predefiniti, i font e il servizio document.
- /integrations/symfony/production-usage/ — sicurezza dei worker e streaming sotto carico.
- /integrations/symfony/troubleshooting/ — problemi comuni di avvio e di runtime.
Conformità
Sezione intitolata “Conformità”Ogni riga è un’affermazione normativa presente in questa pagina, ancorata a un reference_id completo a 64 cifre esadecimali proveniente dal corpus SDO ad accesso riservato. La provenienza (manifest del corpus, trasporto usato per il recupero) è in _sidecars/rag-citations.yaml.
| Specifica | Clausola | reference_id | Affermazione |
|---|---|---|---|
| PSR-11 | psr_11_container#1.1.2.p4 | Contratto degli identificatori has()/get() del container |
Vedere anche
Sezione intitolata “Vedere anche”- /integrations/symfony/overview/ — riepilogo delle funzionalità.
- /integrations/symfony/install/ — installazione e registrazione.
- /integrations/symfony/integration/ — riferimento di wiring end-to-end.