Pular para o conteúdo

Início rápido do NextPDF com Symfony

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.

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.

src/Controller/InvoiceController.php
<?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).

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.

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).

Quando symfony/messenger estiver instalado, você pode mover a geração para fora da thread da requisição.

Implemente NextPDF\Symfony\Message\PdfBuilderInterface. O handler fornece a você um Document novo e pré-configurado, além do contexto serializável da mensagem.

src/Pdf/InvoicePdfBuilder.php
<?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;
}
}

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).

Injete Symfony\Component\Messenger\MessageBusInterface e, em seguida, despache a mensagem:

src/Controller/ReportController.php
<?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).

Em config/packages/messenger.yaml, roteie a mensagem para um transporte:

framework:
messenger:
transports:
async: '%env(MESSENGER_TRANSPORT_DSN)%'
routing:
NextPDF\Symfony\Message\GeneratePdfMessage: async

Em seguida, execute um worker:

Terminal window
php bin/console messenger:consume async
Terminal window
php bin/console debug:container --tag=container.service_locator
php bin/console messenger:consume async --limit=1 -vv

O primeiro comando confirma que o locator de builders está registrado. O segundo consome uma mensagem enfileirada e imprime o progresso do handler.

  • /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.

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çãoCláusulareference_idAfirmação
PSR-11psr_11_container#1.1.2.p4Contrato do identificador has()/get() do container
  • /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.