Use o compat-legacy em produção
Visão geral
Seção intitulada “Visão geral”O adaptador pode ser executado com segurança em manipuladores de Hypertext Transfer Protocol (HTTP), workers de fila e processos de longa duração. Ele é mais seguro que o TCPDF legado 6.2.13 porque elimina os dois riscos de produção que você tem maior probabilidade de encontrar: saída direta para o buffer e die() em caso de erro. Use esta página para operá-lo corretamente.
Antes de ir para produção, conclua a auditoria em modo estrito em /integrations/tcpdf-compat/migration/ e implante com o modo estrito desativado.
Tratamento de saída em workers e manipuladores
Seção intitulada “Tratamento de saída em workers e manipuladores”O Output() do TCPDF legado escreve diretamente no buffer de saída ativo. Isso pode corromper respostas em frameworks HTTP e quebrar workers de fila. Em vez disso, o adaptador roteia a saída por uma ponte de destino segura.
Escolha o destino correspondente ao chamador:
| Contexto | Destino | Por quê |
|---|---|---|
| Worker de fila gravando no armazenamento | Output($path, 'F') | Escreve o arquivo e retorna uma string vazia. Não interage com o buffer. |
| Gerar e depois fazer attach/upload | Output($name, 'S') | Retorna os bytes do Portable Document Format (PDF); você controla para onde eles vão. |
| Anexo de e-mail | Output($name, 'E') | Retorna um corpo Multipurpose Internet Mail Extensions (MIME) em base64 com Content-Type: application/pdf. |
| Resposta HTTP que você controla | Output($name, 'S') | Obtém os bytes; então você define os próprios cabeçalhos e o corpo. |
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;use NextPDF\Compat\Tcpdf\TCPDF;
/** * Render an invoice in a queue worker. Returns the storage path. * * @throws \RuntimeException on a render failure (Error() throws, not die()). */function renderInvoiceJob(array $invoice, string $storageDir): string{ $pdf = new TCPDF('P', 'mm', 'A4'); $pdf->SetFont('helvetica', '', 12); $pdf->AddPage(); $pdf->Cell(0, 10, 'Invoice ' . $invoice['number'], 0, 1);
$path = $storageDir . '/invoice-' . $invoice['number'] . '.pdf';
try { $pdf->Output($path, 'F'); // writes file, no buffer pollution } catch (TcpdfNotImplementedException $e) { // Only reachable if strict mode is on — it must NOT be in production. throw new \RuntimeException('Adapter strict-mode gap in production: ' . $e->getMessage(), 0, $e); } catch (\RuntimeException $e) { // Error() throws RuntimeException instead of die(). throw new \RuntimeException('PDF render failed: ' . $e->getMessage(), 0, $e); }
return $path;}Em um manipulador HTTP, prefira 'S' e defina os cabeçalhos você mesmo:
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();$pdf->AddPage();$pdf->SetFont('helvetica', '', 12);$pdf->Cell(0, 10, 'Report');
$bytes = $pdf->Output('report.pdf', 'S');
header('Content-Type: application/pdf');header('Content-Length: ' . strlen($bytes));header('Content-Disposition: inline; filename="report.pdf"');echo $bytes;Tratamento de falhas
Seção intitulada “Tratamento de falhas”Error() lança RuntimeException; ele nunca chama die(). Essa é a principal mudança operacional em relação ao TCPDF legado.
- Envolva todo ponto de entrada de renderização em
try/catch. - Mapeie a exceção para o contrato de erro da sua aplicação, como HTTP 5xx, job com falha, nova tentativa ou dead-letter.
- Não presuma que o processo termina quando a renderização falha; ele não termina.
Uma TcpdfNotImplementedException em um job periódico de continuous integration (CI) em modo estrito (recomendado) é um achado real. Isso significa que um caminho de código depende de um parâmetro do TCPDF não suportado. Trate isso como um item de trabalho de migração, não como um teste instável.
Ciclo de vida e tratamento de recursos
Seção intitulada “Ciclo de vida e tratamento de recursos”- O documento constrói os bytes do PDF sob demanda na primeira chamada de saída. O
Close()é opcional; ao chamá-lo, os bytes ficam em cache. OOpen()é um no-op seguro. endPage()não faz nada porque o NextPDF gerencia o ciclo de vida das páginas. Remova-o de loops críticos; ele não agrega valor.- Deixe o PHP fazer a coleta de lixo do adaptador entre os jobs. O
_destroy()redefine os dados em cache do adaptador, mas você não precisa chamá-lo explicitamente em loops normais de worker. - Crie um novo adaptador para cada documento. Não reutilize uma instância de adaptador entre documentos não relacionados em um worker de longa duração; o estado do documento fica na instância.
Orientações de desempenho
Seção intitulada “Orientações de desempenho”- O adaptador é uma camada fina de delegação; o motor concentra o custo, não o adaptador.
- Defina as constantes legadas uma única vez na inicialização. O
LegacyDefaults::register()e oLegacyBootstrap::enableAliases()são idempotentes e protegidos, então chamadas repetidas são baratas. Definir constantes por requisição desperdiça trabalho. - Prefira
Output(..., 'S')ou'F'em vez de'I'/'D'em contextos que não sejam de navegador. Os caminhos inline/download produzem uma saída independente de framework que normalmente você não quer em um worker. - Para geração em alto volume, faça o profiling do motor, não do adaptador. A sobrecarga por página do próprio adaptador é pequena em relação à renderização.
Concorrência
Seção intitulada “Concorrência”- Cada instância de adaptador é independente e mantém o próprio estado de documento. A concorrência no nível de processo ou worker é segura quando cada unidade de trabalho usa a própria instância de adaptador.
- As proteções de idempotência em
LegacyBootstrapeLegacyDefaultsusam estado estático local ao processo; elas são seguras nos modelos típicos do PHP per-request/per-worker. Elas não foram projetadas para compartilhar estado mutável entre threads.
Checklist de pré-produção
Seção intitulada “Checklist de pré-produção”- Auditoria em modo estrito concluída; o ambiente de produção executa com o modo estrito desativado.
- Todos os pontos de entrada de renderização envolvidos em
try/catchparaRuntimeException(sem depender dedie()). - Os workers usam
Output(..., 'F')ou'S', nunca o caminho inline. - Constantes legadas definidas uma única vez na inicialização, antes da primeira construção.
- Um job de CI periódico em modo estrito está em vigor para detectar regressões.
- As asserções de teste em nível de byte foram reescritas como uma nova baseline (consulte /integrations/tcpdf-compat/migration/).
Veja também
Seção intitulada “Veja também”- /integrations/tcpdf-compat/security-and-operations/ — criptografia, postura de assinatura e fortalecimento
- /integrations/tcpdf-compat/troubleshooting/ — padrões de falha em produção e correções
- /integrations/tcpdf-compat/configuration/ — modo estrito e higiene de constantes
- /integrations/tcpdf-compat/migration/ — a auditoria que deve preceder a produção