Pular para o conteúdo

Solução de problemas do pacote Laravel para NextPDF

Use esta página para mapear cada falha observável no pacote até sua causa raiz verificada no código-fonte. Cada entrada traz o sintoma, a causa e a correção.

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

A maioria dos problemas relatados se encaixa em cinco grupos: descoberta, resolução no container, assinatura, jobs de fila e nomes de arquivo do Hypertext Transfer Protocol (HTTP). Por design, o pacote falha de forma explícita. Recursos opcionais que não estão configurados retornam null, e entradas inseguras lançam exceções tipadas. O sintoma costuma apontar diretamente para a causa.

SintomaCausa verificadaCorreção
O provider não é registrado após a instalaçãoA aplicação desativa a descoberta com extra.laravel.dont-discoverRemova o pacote de dont-discover ou registre NextPdfServiceProvider manualmente em bootstrap/providers.php
config('nextpdf') está vazioA configuração não foi mesclada porque nenhum binding anunciado foi resolvido (provider adiado)Resolva qualquer entrada de provides(), ou confirme a descoberta com php artisan package:discover --ansi
config/nextpdf.php não foi criado pela publicaçãoTag de publicação incompatívelUse a tag exata: php artisan vendor:publish --tag=nextpdf-config
RuntimeException: “NextPDF requires the ext-mbstring/ext-zlib PHP extension”Uma extensão obrigatória do Hypertext Preprocessor (PHP) não está disponível em tempo de execuçãoInstale ou habilite mbstring e zlib em php.ini
SintomaCausa verificadaCorreção
app(SignerInterface::class) retorna nullA assinatura está desativada ou o certificado está vazio em nextpdf.signatureDefina signature.enabled = true e um signature.certificate válido; instale nextpdf/premium para fornecer o concreto do signatário
app(TsaClient::class) retorna nullnextpdf.tsa.url está vazioConfigure tsa.url (e credentials/pins conforme necessário)
Class-not-found para um tipo de versão PDF/Anextpdf.pdfa não é null, mas nextpdf/premium não está instaladoInstale nextpdf/premium ou defina pdfa novamente como null
Class-not-found ao resolver um contrato de e-invoiceOs bindings estão registrados, mas os concretos do Premium estão ausentesInstale nextpdf/premium; os contratos de e-invoice são resolvidos de forma lazy e falham apenas na primeira resolução sem o Premium
Mesmo documento mutado em duas operações lógicasO binding do documento é uma factory; você reutilizou uma única instância já resolvidaResolva um novo PdfDocumentInterface para cada documento

Um container sem determinada entrada lança uma exceção not-found em get() (PHP Standard Recommendation 11 (PSR-11) §1.1.2). Os contratos de e-invoice estão vinculados, portanto o has() do container retorna true. O concreto ausente do Premium gera o erro no momento da construção, não no próprio container.

SintomaCausa verificadaCorreção
InvalidArgumentException: Path traversal sequences are not allowedO caminho de saída contém um segmento .. de travessiaUse um caminho absoluto, sem segmentos de travessia, dentro do diretório de armazenamento
InvalidArgumentException: Stream wrappers are not allowedO caminho usa um esquema como php://Use um caminho simples do sistema de arquivos
InvalidArgumentException: Output path contains null bytesO caminho contém um byte \0 nuloSanitize o caminho antes do dispatch
InvalidArgumentException: Output path must end with .pdf extensionO caminho não termina em .pdf (sem diferenciar maiúsculas de minúsculas)Use um sufixo .pdf (ou .PDF)
O job executa, mas o arquivo está vazio ou incorretoA closure de construção não retornou o documento configuradoRetorne o documento pela closure de construção; o job salva o valor retornado
O job usa a fila ou o timeout erradonextpdf.queue.* não está definido conforme esperadoDefina queue.queue, queue.connection e queue.timeout; tries e backoff exigem subclassing

As verificações de caminho são executadas dentro de handle() no worker; portanto, um caminho inválido falha durante a execução, e não no dispatch. Isso é intencional: o worker valida o payload serializado da fila no momento em que o consome.

SintomaCausa verificadaCorreção
O nome de arquivo de download é document.pdf inesperadamenteVocê passou um nome de arquivo vazio; a factory usa o padrãoPasse um nome de arquivo não vazio
O nome de arquivo perdeu o caminho ou os caracteres especiaisO sanitizador de nome de arquivo remove separadores de caminho, caracteres de controle e bytes nulosPasse apenas o nome de arquivo base; esse reforço de segurança é esperado
O nome de arquivo não ASCII aparece como mojibake em alguns clientesA resposta emite o Request for Comments 5987 (RFC 5987) filename*= para nomes não ASCII; clientes antigos leem o fallback ASCIIEsperado; forneça um nome compatível com ASCII se um cliente legado precisar corresponder exatamente
A resposta em streaming não tem Content-LengthAs respostas em streaming omitem Content-Length por design (saída em chunks)Esperado; use as variantes não-streaming inline()/download() se for necessário um cabeçalho de comprimento
Terminal window
# Confirm the provider is discovered
php artisan package:discover --ansi
# Inspect merged configuration
php artisan tinker --execute="dump(config('nextpdf.queue'));"
resource: src/Laravel/NextPdfServiceProvider.php (null-check pattern)
<?php
declare(strict_types=1);
use NextPDF\Contracts\SignerInterface;
$signer = app(SignerInterface::class);
if ($signer === null) {
// Signing not configured, or nextpdf/premium not installed.
// Continue without a signature, or fail with a clear message.
}
  • Com o provider adiado, uma instalação recém-feita pode parecer “quebrada” até a primeira resolução relevante. Considere o fato de package:discover listar o pacote como o sinal de sucesso.
  • Quando image_cache_mb = null, o pacote recorre a 50 MB; somente 0 desativa o cache. Um relato de “cache não desativa” normalmente usou null.
  • Quando signature.level = null, o pacote recorre silenciosamente ao PDF Advanced Electronic Signatures (PAdES) B-B. Um relato de “B-B inesperado” normalmente deixou o nível indefinido.

Se as primeiras requisições em um worker de longa duração estiverem lentas, o registro de fontes está fazendo o parsing sob demanda. Preencha nextpdf.preload_fonts para que o aquecimento seja executado uma vez no boot do worker. Consulte /integrations/laravel/configuration/ e /integrations/laravel/boot-and-discovery/ para mais detalhes.

As rejeições de caminho e de nome de arquivo são controles de segurança, não bugs. Não as contorne pré-decodificando ou relaxando as verificações. Em vez disso, encaminhe a saída de arquivos por um caminho de armazenamento controlado. Consulte /integrations/laravel/security-and-operations/.

AfirmaçãoFonteCláusulareference_id
Entrada ausente no container lança not-found em get()PSR-11 Container§1.1.2
  • /integrations/laravel/install/ — passos de descoberta e publicação
  • /integrations/laravel/configuration/ — cada chave e seu valor padrão
  • /integrations/laravel/production-usage/ — injeção de dependência (DI) e padrões de fila
  • /integrations/laravel/security-and-operations/ — por que as verificações de caminho existem