Guia do desenvolvedor Symfony
Visão geral
Seção intitulada “Visão geral”O pacote Symfony prioriza os serviços. Injete PdfFactory, chame create() para cada documento Portable Document Format (PDF) e use os builders do Messenger para geração assíncrona. Você pode manter a factory como um serviço do container porque cada chamada retorna um documento novo.
Use este guia quando você projetar controllers, serviços, handlers do Messenger ou pontos de extensão no nível do bundle para nextpdf/symfony.
Limite de arquitetura
Seção intitulada “Limite de arquitetura”| Camada | Pertence a | Responsabilidade | Não coloque aqui |
|---|---|---|---|
| Controller | Aplicação | Autorize a requisição, colete a entrada e retorne PdfResponse. | Layout de PDF compartilhado entre casos de uso. |
| Serviço de aplicação | Aplicação | Carregue os dados de domínio e selecione um builder. | Lógica do compilador do container Symfony. |
| Serviço builder | Aplicação | Implemente PdfBuilderInterface para construção de documentos síncrona ou enfileirada. | Objetos de requisição, entity managers ou contexto não serializável. |
| Bundle Symfony | nextpdf/symfony | Registra serviços, a árvore de configuração, o passe de extensão opcional, os helpers de resposta e os data transfer objects (DTOs) do Messenger. | Política de armazenamento específica do tenant. |
| Motor principal | nextpdf/nextpdf | Cria e serializa o documento. | Comportamento de resposta do Symfony ou do Messenger. |
Ciclo de vida em tempo de execução
Seção intitulada “Ciclo de vida em tempo de execução”| Etapa | Comportamento | Ação do desenvolvedor |
|---|---|---|
| Inicialização do bundle | NextPdfBundle::build() registra a detecção de extensões opcionais. | Deixe o Symfony descobrir o bundle ou registre-o em bundles.php. |
| Carregamento de configuração | NextPdfExtension::load() processa a configuração nextpdf: e carrega as definições de serviço. | Mantenha a configuração explícita e adaptada ao ambiente. |
| Uso da factory | PdfFactory::create() retorna um documento novo e já configurado. | Não armazene documentos em serviços. |
| Saída do controller | PdfResponse transforma um documento concluído em uma resposta. | Use o helper em vez de montar os headers manualmente. |
| Despacho do Messenger | GeneratePdfMessage carrega a classe do builder, o caminho de saída e o contexto serializável. | Mantenha o contexto mínimo e composto preferencialmente por valores escalares. |
| Tratamento de mensagens | GeneratePdfHandler resolve o builder a partir de um service locator e salva o documento. | Faça os builders determinísticos e idempotentes. |
Estrutura de aplicação recomendada
Seção intitulada “Estrutura de aplicação recomendada”| Caminho | Finalidade |
|---|---|
src/Pdf/Builder/* | Serviços que implementam PdfBuilderInterface. |
src/Pdf/Data/* | Pequenos DTOs ou arrays usados como contexto do builder. |
src/Pdf/Storage/* | Seleção da raiz de armazenamento e política de nome do arquivo de saída. |
src/Controller/* | Pontos de entrada para respostas síncronas. |
tests/Pdf/* | Testes de builder, de resposta, do Messenger e de configuração. |
Prefira serviços builder em vez de funções helper estáticas. Eles são fáceis de marcar com tags, decorar, testar e usar a partir do Messenger.
<?php
namespace App\Pdf\Builder;
use NextPDF\Core\Document;use NextPDF\Symfony\Message\PdfBuilderInterface;
final readonly class InvoicePdfBuilder implements PdfBuilderInterface{ public function build(Document $document, array $context): Document { $document->setTitle((string) $context['title']) ->addPage() ->writeHtml((string) $context['html']);
return $document; }}Padrão de resposta síncrona
Seção intitulada “Padrão de resposta síncrona”<?php
namespace App\Controller;
use App\Pdf\Builder\InvoicePdfBuilder;use NextPDF\Symfony\Http\PdfResponse;use NextPDF\Symfony\Service\PdfFactory;
final readonly class InvoiceController{ public function __invoke( PdfFactory $factory, InvoicePdfBuilder $builder, ) { $document = $builder->build($factory->create(), [ 'title' => 'Invoice 1234', 'html' => '<h1>Invoice 1234</h1>', ]);
return PdfResponse::download($document, 'invoice-1234.pdf'); }}Mantenha o contexto do controller enxuto. Quando um builder precisar de muitos objetos de domínio, mova a orquestração para um serviço de aplicação e passe um DTO ou um array normalizado para o builder.
Padrão do Messenger
Seção intitulada “Padrão do Messenger”GeneratePdfMessage valida a classe do builder e o caminho de saída antes do despacho. O handler valida o caminho novamente quando é executado.
<?php
use App\Pdf\Builder\InvoicePdfBuilder;use NextPDF\Symfony\Message\GeneratePdfMessage;
$bus->dispatch(new GeneratePdfMessage( builderClass: InvoicePdfBuilder::class, outputPath: $projectDir . '/var/pdfs/invoice-1234.pdf', builderContext: [ 'title' => 'Invoice 1234', 'html' => '<h1>Invoice 1234</h1>', ],));Não coloque entidades do Doctrine, streams abertos, closures, objetos de requisição ou objetos de serviço em builderContext.
Pontos de extensão
Seção intitulada “Pontos de extensão”| Ponto de extensão | Use para | Restrição |
|---|---|---|
PdfFactory decoração de serviço | Aplicar os padrões da aplicação antes que os documentos cheguem aos controllers. | Deve preservar a semântica de documento novo. |
PdfBuilderInterface | Definir builders de documentos enfileirados ou reutilizáveis. | Deve retornar um Document. |
OptionalExtensionPass | Habilitar recursos opcionais do Artisan ou Premium em tempo de compilação. | A disponibilidade é um estado de compilação do container, não um estado de requisição. |
| Árvore de configuração do Symfony | Padrões, PDF/A, configurações do renderizador, assinatura, autoridade de carimbo de tempo (TSA) e Messenger. | Uma configuração inválida deve falhar durante a construção do container. |
GeneratePdfHandler conexão de serviço | Restringir quais builders são acessíveis a partir de mensagens enfileiradas. | O service locator deve expor apenas os serviços builder aprovados. |
Fluxo de trabalho de desenvolvimento
Seção intitulada “Fluxo de trabalho de desenvolvimento”- Adicione um serviço builder com entrada determinística.
- Use
PdfFactory::create()em um controller ou serviço. - Adicione um teste de resposta para o nome do arquivo, o content type e os headers.
- Registre o builder no Messenger quando o mesmo documento precisar ser gerado de forma assíncrona.
- Adicione testes de mensagem inválida para o nome da classe, o caminho de saída e o formato do contexto.
- Adicione um teste de compilação do container com configuração mínima e de produção.
- Meça o tempo de renderização e a memória sob as mesmas configurações de PHP usadas em produção.
Tratamento de falhas
Seção intitulada “Tratamento de falhas”| Falha | Onde deve ser tratada | Resposta recomendada |
|---|---|---|
| Configuração inválida | Compilação do container. | Faça o deploy falhar antes que o tráfego chegue à aplicação. |
| Serviço builder ausente | Testes do handler do Messenger e tags de serviço. | Faça a mensagem falhar e alerte a equipe responsável. |
| Caminho de saída inseguro | Construtor da mensagem e política de armazenamento. | Rejeite-o antes do despacho; mantenha a validação no handler como defesa em profundidade. |
| Extensão opcional indisponível | Passe do compilador e comportamento da factory. | Desabilite o recurso opcional ou torne a instalação explícita. |
| Falha de conversão de serviço ou de renderização | Fronteira do builder. | Falhe de forma fechada, a menos que o caso de uso tenha um fallback documentado. |
Padrões seguros
Seção intitulada “Padrões seguros”| Aspecto | Padrão | Quando sobrescrever |
|---|---|---|
| Tempo de vida da factory | Serviço do container. | Mantenha assim; a factory é segura porque cria documentos novos. |
| Tempo de vida do documento | Uma unidade de trabalho. | Nunca compartilhe entre requisicoes ou mensagens. |
| Validação do caminho de saída | Construtor da mensagem e handler. | Adicione restrições de tenant ou de raiz de armazenamento no código da aplicação. |
| Nome do arquivo de resposta | document.pdf. | Sobrescreva com identificadores de negócio higienizados. |
| Transporte do Messenger | async. | Use um transporte dedicado quando o trabalho de PDF for pesado. |
Lista de verificação de testes
Seção intitulada “Lista de verificação de testes”- Os testes de container compilam o bundle com configuração mínima e de produção.
- Os testes de resposta verificam os headers de segurança e o tratamento do nome do arquivo.
- Os testes do Messenger verificam que caminhos inválidos e nomes de classe de builder inválidos falham antes do despacho.
- Os testes do handler usam um serviço builder real e um diretório de saída temporário.
- Os testes de builder renderizam um documento representativo e o salvam com permissões de sistema de arquivos semelhantes às de produção.
- Os testes de extensão opcional cobrem Artisan indisponível, Premium indisponível e o comportamento do perfil PDF/A configurado.