Pular para o conteúdo

NextPDF no Laravel: boot e descoberta automática

O Laravel descobre automaticamente o NextPdfServiceProvider a partir do composer.json do pacote. O provider registra bindings adiados no container e, em contexto de console, publica o arquivo de configuração. Esta página explica como a descoberta funciona e qual é o ciclo de vida de cada binding.

Terminal window
composer require nextpdf/laravel
php artisan vendor:publish --tag=nextpdf-config

O pacote declara o provider e o alias de facade no bloco extra.laravel do seu próprio composer.json:

resource: composer.json (extra.laravel)
{
"extra": {
"laravel": {
"providers": [
"NextPDF\\Laravel\\NextPdfServiceProvider"
],
"aliases": {
"Pdf": "NextPDF\\Laravel\\Facades\\Pdf"
}
}
}
}

Quando você executa composer require, o Laravel lê esse bloco e então registra o provider e o alias. Você não precisa editar manualmente o config/app.php nem o bootstrap/providers.php. O array extra.laravel.providers registra automaticamente os service providers, e extra.laravel.aliases registra automaticamente os aliases de facade (guia de desenvolvimento de pacotes do Laravel 12, https://laravel.com/docs/12.x/packages, acessado em 2026-05-18).

NextPdfServiceProvider implementa DeferrableProvider e o ciclo de vida padrão register() / boot().

  1. register() mescla a configuração do pacote sob a chave nextpdf. Em seguida, vincula as entradas do container: registro de fontes, registro de imagens, fábrica de documentos, cliente Hypertext Transfer Protocol (HTTP) compatível com PHP Standards Recommendation 18 (PSR-18), cliente de timestamp, signer, documento e contratos de e-invoice. Cada binding é uma closure, portanto nada pesado é construído aqui.
  2. boot() verifica se as extensões PHP mbstring e zlib estão carregadas. Ele registra a configuração publicável sob a tag nextpdf-config apenas quando runningInConsole() é verdadeiro.

Como o provider é adiado, register() só é executado quando você resolve uma das entradas retornadas por provides(). Resolver uma chave de container não relacionada não inicializa o NextPDF.

A PHP Standards Recommendation 11 (PSR-11) permite que duas chamadas get() sucessivas com o mesmo identificador retornem valores diferentes, dependendo da estratégia de binding (PSR-11 §1.1.2). O provider depende desse comportamento por design:

Chave de bindingTempo de vidaObservações
FontRegistryInterface (+ alias FontRegistry)singleton, travado após o warmupAquecido a partir de preload_fonts; travado para que nenhuma requisição consiga alterá-lo
ImageRegistrysingletonCache least recently used (LRU) limitado, dimensionado por image_cache_mb; não travado
DocumentFactoryInterface (+ alias DocumentFactory)singletonSem estado; compartilha os dois registros
Psr\Http\Client\ClientInterfacesingletonCliente com proteção contra request-forgery que encapsula um cliente curl; construído a partir de tsa.*
TsaClientscopednull quando tsa.url está vazio
SignerInterfacefactorynull quando a assinatura está desabilitada ou o certificado está vazio
PdfDocumentInterface (+ alias nextpdf)factoryNovo NextPDF\Core\Document a cada resolução, com os metadados padrão aplicados
EmbedderInterface, ValidatorInterface, ProfileInterface, SchematronRunnerInterfacefactoryResolvem para implementações concretas Premium; geram erro na primeira resolução sem nextpdf/premium

O binding de documento aplica defaults.creator, defaults.language e, quando não está vazio, defaults.author a cada novo documento. Quando pdfa não é nulo, ele habilita PDF/A (Premium). Quando a seção artisan está presente e existe uma classe browser-factory do Chrome, ele aplica a configuração do renderizador Chrome.

has() no container recebe um único identificador de string (PSR-11 §1.1.2). Os contratos de e-invoice estão vinculados, portanto has() retorna verdadeiro para eles mesmo quando o Premium está ausente. A ausência da implementação concreta só gera erro na construção.

Adicione o pacote ao array dont-discover da aplicação e, depois, registre o provider manualmente:

resource: application composer.json
{
"extra": {
"laravel": {
"dont-discover": ["nextpdf/laravel"]
}
}
}
resource: bootstrap/providers.php
<?php
declare(strict_types=1);
return [
App\Providers\AppServiceProvider::class,
NextPDF\Laravel\NextPdfServiceProvider::class,
];

Cada chave é resolvida nesta ordem: variável de ambiente → valor publicado em config/nextpdf.php → padrão do pacote mesclado em register(). A maioria das chaves aceita um nome NEXTPDF_* ou um nome de ambiente legado TCPDF_*. Prefira NEXTPDF_*.

Terminal window
php artisan package:discover --ansi

Uma linha que lista nextpdf/laravel confirma a descoberta. Como o provider é adiado, os próprios bindings só aparecem após a primeira resolução. A linha de descoberta é o sinal correto de sucesso.

  • A publicação da configuração é registrada apenas em contexto de console, portanto uma requisição exclusivamente web nunca a aciona. Execute vendor:publish a partir da interface de linha de comando (CLI).
  • Além das chaves de registro, fábrica, cliente HTTP, signer, timestamp e documento, provides() inclui as quatro chaves de contrato de e-invoice.
  • Uma instalação recém-feita pode parecer inerte até a primeira resolução relevante. Isso faz parte do design de provider adiado, não é uma falha.

register() é O(1) porque cria apenas closures. O warmup do registro de fontes é O(f) em fontes pré-carregadas e executa uma vez por processo worker. Adiar o provider mantém o custo de construção do NextPDF fora do fluxo de boot do framework até que um binding seja efetivamente usado.

O design adiado reduz a superfície de ataque no boot. O registro de fontes travado impede que uma requisição altere o estado das fontes de outra em workers de longa duração. Para a cobertura completa de ameaças, consulte /integrations/laravel/security-and-operations/.

AfirmaçãoFonteCláusulareference_id
Resoluções sucessivas podem diferir conforme a estratégia de bindingPSR-11 Container§1.1.2
has() recebe um identificador de stringPSR-11 Container§1.1.2

A documentação oficial de pacotes do Laravel 12 confirma os nomes das chaves de descoberta do Laravel (https://laravel.com/docs/12.x/packages, acessado em 2026-05-18).

As implementações concretas Premium são resolvidas pelas mesmas chaves de binding adiado. Essa capacidade Enterprise opcional não exige alteração de código no pacote Core documentado aqui. Consulte https://nextpdf.dev/get-license/?intent=laravel-signing.

  • /integrations/laravel/install/ — instalar e publicar
  • /integrations/laravel/overview/ — arquitetura do pacote
  • /integrations/laravel/integration/ — guia how-to de wiring de ponta a ponta
  • /integrations/laravel/configuration/ — cada chave de configuração