Pular para o conteúdo

Guia do desenvolvedor Laravel

O pacote Laravel adapta o NextPDF às convenções do Laravel sem alterar o ciclo de vida do documento no core. O container é responsável pelos registries e pelas factories compartilhados. Cada documento PDF é descartável; portanto, você deve construí-lo, retorná-lo, transmiti-lo ou salvá-lo uma única vez.

Use este guia ao projetar serviços de aplicação, jobs de fila, fluxos de resposta ou cobertura de testes para o nextpdf/laravel.

CamadaPertence aResponsabilidadeNão coloque aqui
ControllerAplicaçãoAutorizar a requisição, escolher um document builder e retornar uma resposta.Regras de layout do PDF compartilhadas entre casos de uso.
Serviço de aplicaçãoAplicaçãoColetar dados de domínio e chamar o código de construção do documento.Lógica de inicialização do container ou configuração do pacote.
Document builderAplicaçãoTraduzir dados de domínio em chamadas de documento do NextPDF.Objetos de requisição, lógica de consultas do Eloquent ou detalhes de transporte da fila.
Integração com Laravelnextpdf/laravelRegistrar factories, registries, signer, cliente TSA, facade, responses e queue job.Caminhos de armazenamento específicos do negócio ou política de tenant.
Motor corenextpdf/nextpdfConstruir e serializar o PDF.Política de response, fila ou sistema de arquivos do Laravel.
EtapaComportamentoAção do desenvolvedor
Registro do service providerNextPdfServiceProvider::register() registra os registries compartilhados, a document factory, o document binding, o cliente HTTP, o cliente da autoridade de carimbo do tempo (TSA), o signer e os contratos opcionais de e-invoice.Publique e revise o config/nextpdf.php antes da produção.
Resolução do documentoO facade Pdf e o binding PdfDocumentInterface resolvem um documento novo por meio do DocumentFactoryInterface.Resolva um documento uma vez por requisição, comando ou job enfileirado.
AutoriaO código da aplicação chama as APIs de documento do core por meio do facade ou do documento injetado.Mantenha a extração de dados de domínio fora do document builder.
Saída terminalPdfResponse emite a saída HTTP, ou o documento é salvo em disco.Escolha um único caminho de saída terminal por documento.
Execução na filaGeneratePdfJob reconstrói o documento no worker e valida novamente o caminho de saída.Passe contexto escalar e mantenha os callbacks idempotentes.
CaminhoFinalidade
app/Pdf/Builders/*Document builders puros. Eles recebem dados e retornam um documento completo.
app/Pdf/Data/*Pequenos objetos de transferência de dados (DTOs) que carregam entradas de documento já autorizadas.
app/Services/*Orquestração da aplicação, consultas, repasse de autorização e seleção do caminho de armazenamento.
app/Jobs/*Wrappers opcionais em torno do GeneratePdfJob quando a aplicação precisa de jobs nomeados.
tests/Feature/Pdf/*Testes de resposta HTTP, dispatch de fila e autorização.
tests/Unit/Pdf/*Testes de builder com entradas pequenas e determinísticas.

Mantenha os builders independentes dos objetos de requisição do Laravel. Você deve conseguir chamar um builder a partir de um controller, comando, teste ou queue worker com a mesma entrada.

<?php
namespace App\Pdf\Builders;
use App\Pdf\Data\InvoicePdfData;
use NextPDF\Contracts\PdfDocumentInterface;
final readonly class InvoicePdfBuilder
{
public function build(PdfDocumentInterface $pdf, InvoicePdfData $data): PdfDocumentInterface
{
$pdf->setTitle($data->title)
->addPage()
->setFont('dejavusans', '', 12)
->writeHtml($data->html);
return $pdf;
}
}

Use injeção via construtor quando o fluxo de PDF fizer parte da lógica da aplicação. Use o facade apenas em fluxos curtos de controller, em que o estilo estático é mais fácil de ler.

<?php
namespace App\Http\Controllers;
use App\Pdf\Builders\InvoicePdfBuilder;
use App\Pdf\Data\InvoicePdfData;
use NextPDF\Contracts\PdfDocumentInterface;
use NextPDF\Laravel\Http\PdfResponse;
final readonly class DownloadInvoiceController
{
public function __invoke(
PdfDocumentInterface $pdf,
InvoicePdfBuilder $builder,
) {
$document = $builder->build(
$pdf,
InvoicePdfData::fromInvoiceId(1234),
);
return PdfResponse::download($document, 'invoice-1234.pdf');
}
}

Os helpers de resposta materializam os bytes do documento antes de construir a resposta do Laravel. Eles são helpers de resposta, não renderizadores em segundo plano.

GeneratePdfJob aceita um callable de builder e um caminho de saída. O job valida caminhos inseguros em tempo de execução. O código da aplicação ainda deve escolher uma raiz de armazenamento segura para o tenant antes do dispatch.

<?php
use App\Pdf\Builders\QueuedInvoiceBuilder;
use NextPDF\Laravel\Jobs\GeneratePdfJob;
GeneratePdfJob::dispatch(
outputPath: storage_path('app/pdfs/invoice-1234.pdf'),
builder: [QueuedInvoiceBuilder::class, 'build'],
)->onQueue(config('nextpdf.queue.queue', 'pdf'));

Mantenha os callbacks de fila pequenos. Prefira gravar estado durável a partir de um job listener da aplicação, em vez de armazenar closures complexas no payload da fila.

Ponto de extensãoUse paraRestrição
PdfDocumentInterface (binding)Substituir ou decorar a criação de documentos para padrões que valem em toda a aplicação.Deve retornar uma instância nova de documento.
DocumentFactoryInterfaceCriar documentos novos explicitamente em serviços e testes.Não armazene em cache os documentos retornados.
config/nextpdf.phpPadrões, configurações de fila, configurações do renderizador Chrome, hooks de assinatura, TSA e cache OCSP.Trate as variáveis de ambiente como configuração de deployment, não como entrada de requisição.
GeneratePdfJob (builder)Construir documentos de forma assíncrona.O callable deve ser serializável pelo transporte de fila do Laravel.
Callbacks de sucesso/falhaNotificação ou limpeza após a geração.Mantenha os callbacks idempotentes e atentos a efeitos colaterais.
Contratos Premium opcionaisEmbedder, validador, profile e runner Schematron de e-invoice.Resolva apenas onde o pacote opcional está instalado e licenciado.
  1. Construa o primeiro documento de forma síncrona em um controller ou feature test.
  2. Mova o código de layout para uma classe builder em app/Pdf/Builders.
  3. Mova a lógica de consultas e de autorização para um serviço de aplicação.
  4. Adicione testes de PdfResponse para cabeçalhos e nomes de arquivo.
  5. Mova a geração lenta ou de alto volume para o GeneratePdfJob.
  6. Adicione testes de fila para contexto serializado, política de caminho de saída e tratamento de falhas.
  7. Meça o consumo de memória e o tempo de renderização com dados de produção representativos.
FalhaOnde deve ser tratadaResposta recomendada
Requisição inválida ou documento não autorizadoController ou policy.Retorne a resposta normal de autorização ou validação da aplicação.
Fonte ausente ou imagem inválidaTeste de builder e logging da aplicação.Faça a requisição ou o job falhar; não emita PDFs parciais.
Caminho de saída inseguroServiço de armazenamento da aplicação e GeneratePdfJob.Rejeite antes do dispatch e conte com a validação no lado do worker como defesa em profundidade.
Falha de assinatura ou de TSAFronteira do serviço de assinatura.Decida se o documento pode ficar sem assinatura; por padrão, falhe de forma fechada (fail closed) para documentos regulados.
Timeout da filaConfiguração e observabilidade do queue worker.Reexecute apenas quando o builder for determinístico e o caminho de saída for seguro de sobrescrever.
AspectoPadrãoQuando substituir
Nome da filapdfUse uma fila dedicada quando a geração concorrer com jobs voltados ao usuário.
Timeout do job120 segundosAumente somente após medir o tamanho do documento e a capacidade do worker.
Nome do arquivo de respostadocument.pdfUse identificadores de negócio sanitizados.
Registry de fontesCompartilhado e bloqueado após o warmup.Adicione preload_fonts para fontes usadas em hot paths.
Registry de imagensCache compartilhado e limitado.Reduza image_cache_mb para workers com pouca memória.
Fragmentação da resposta transmitidaChunks de 64 KB.Não dependa dos limites dos chunks; eles são um detalhe de saída.
  • Os testes de controller verificam Content-Type, Content-Disposition e cabeçalhos defensivos.
  • Os testes de builder usam DTOs determinísticos e não consultam o banco de dados.
  • Os testes de fila verificam se o builder recebe um documento novo.
  • Os testes de caminho cobrem traversal, stream-wrapper, null-byte e rejeição de arquivos que não sejam .pdf.
  • Os testes de worker renderizam documentos representativos sob o mesmo limite de memória que a produção.
  • Os testes opcionais de assinatura cobrem certificado ausente, senha inválida, TSA indisponível e nível de assinatura configurado.