Início rápido do NextPDF com Symfony
Visão geral
Seção intitulada “Visão geral”Injete PdfFactory, construa um Document e retorne-o por meio de PdfResponse. Quando você precisar gerar em segundo plano, despache um GeneratePdfMessage para um transporte do Messenger.
Etapa 1 — Gerar um PDF em um controller
Seção intitulada “Etapa 1 — Gerar um PDF em um controller”Injete NextPDF\Symfony\Service\PdfFactory. O método create() retorna um novo NextPDF\Core\Document e aplica os padrões configurados para criador, autor e idioma. Retorne o documento com 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() retorna um Symfony\Component\HttpFoundation\Response. Ele define Content-Type: application/pdf, a disposição como attachment, Content-Length e os cabeçalhos de segurança fixos do bundle. O Symfony documenta a classe Response padrão e o respectivo modelo de cabeçalhos (https://symfony.com/doc/current/components/http_foundation.html).
Etapa 2 — Exibir um PDF inline
Seção intitulada “Etapa 2 — Exibir um PDF inline”Use inline() quando quiser que o navegador exiba o PDF em vez de baixá-lo:
return PdfResponse::inline($doc, 'preview.pdf');A disposição passa a ser inline. Todos os demais cabeçalhos permanecem iguais.
Etapa 3 — Fazer streaming de um PDF grande
Seção intitulada “Etapa 3 — Fazer streaming de um PDF grande”Use as variantes de streaming para documentos grandes. Elas emitem o PDF em blocos de 64 KB, o que reduz o pico de memória. Essas variantes retornam um Symfony\Component\HttpFoundation\StreamedResponse e omitem Content-Length.
return PdfResponse::streamDownload($doc, 'annual-report.pdf');Use streamInline() para streaming inline. O Symfony documenta o contrato de callback do StreamedResponse, que é um callable void responsável por liberar a saída (https://symfony.com/doc/current/components/http_foundation.html).
Etapa 4 — Gerar um PDF de forma assíncrona
Seção intitulada “Etapa 4 — Gerar um PDF de forma assíncrona”Quando symfony/messenger estiver instalado, você pode mover a geração para fora da thread da requisição.
4a — Implementar um builder
Seção intitulada “4a — Implementar um builder”Implemente NextPDF\Symfony\Message\PdfBuilderInterface. O handler fornece a você um Document novo e pré-configurado, além do contexto serializável da mensagem.
<?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 — Registrar o builder no locator
Seção intitulada “4b — Registrar o builder no locator”O handler resolve builders por meio de um service locator PHP Standard Recommendation 11 (PSR-11) indexado por nome de classe. Apenas builders registrados ficam acessíveis. Adicione o builder a um locator em 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'O handler solicita o builder ao locator usando o id class-string. No PSR-11, um identificador de container é uma string que identifica uma entrada de maneira única (PSR-11 §1.1.2).
4c — Despachar a mensagem
Seção intitulada “4c — Despachar a mensagem”Injete Symfony\Component\Messenger\MessageBusInterface e, em seguida, despache a mensagem:
<?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 é um data transfer object (DTO) readonly. O construtor rejeita caminhos de saída vazios, que não terminem em .pdf, incluam segmentos de path traversal, usem esquemas de stream wrapper ou contenham bytes nulos. Ele também exige que builderClass seja um nome de classe sintaticamente válido. O handler valida novamente o caminho de saída em tempo de execução, antes de escrever. Se um caminho for seguro no despacho, mas inseguro no momento do consumo, o handler ainda assim o rejeita. O atributo #[AsMessageHandler] e o contrato de despacho do MessageBusInterface seguem o modelo padrão do Symfony Messenger (https://symfony.com/doc/current/messenger.html).
4d — Rotear a mensagem e executar um worker
Seção intitulada “4d — Rotear a mensagem e executar um worker”Em config/packages/messenger.yaml, roteie a mensagem para um transporte:
framework: messenger: transports: async: '%env(MESSENGER_TRANSPORT_DSN)%' routing: NextPDF\Symfony\Message\GeneratePdfMessage: asyncEm seguida, execute um worker:
php bin/console messenger:consume asyncVerifique se funciona
Seção intitulada “Verifique se funciona”php bin/console debug:container --tag=container.service_locatorphp bin/console messenger:consume async --limit=1 -vvO primeiro comando confirma que o locator de builders está registrado. O segundo consome uma mensagem enfileirada e imprime o progresso do handler.
Próximos passos
Seção intitulada “Próximos passos”- /integrations/symfony/configuration/ — ajuste os padrões, as fontes e o serviço de documento.
- /integrations/symfony/production-usage/ — revise a segurança do worker e o streaming sob carga.
- /integrations/symfony/troubleshooting/ — resolva problemas comuns de inicialização e tempo de execução.
Conformidade
Seção intitulada “Conformidade”Cada linha é uma afirmação normativa desta página vinculada a um reference_id completo de 64 hex do corpus controlado da standards development organization (SDO). _sidecars/rag-citations.yaml contém a proveniência, incluindo o manifesto do corpus e o transporte de recuperação.
| Especificação | Cláusula | reference_id | Afirmação |
|---|---|---|---|
| PSR-11 | psr_11_container#1.1.2.p4 | Contrato do identificador has()/get() do container |
Veja também
Seção intitulada “Veja também”- /integrations/symfony/overview/ — revise o resumo de funcionalidades.
- /integrations/symfony/install/ — instale e registre o bundle.
- /integrations/symfony/integration/ — revise a referência de integração de ponta a ponta.