Pular para o conteúdo

Migração do TCPDF 6.x para o NextPDF

Migre em uma ordem clara. Primeiro, passe para o motor NextPDF com a menor mudança possível. Valide o que já funciona. Audite o que não funciona. Corrija cada local de chamada. Depois, remova o adaptador. A camada de compatibilidade dá suporte às etapas dois a quatro; ela não é o destino.

Esta página apresenta a estratégia. Para entender o comportamento exato de cada método, use /integrations/tcpdf-compat/method-coverage/ junto com a matriz oficial no repositório docs/TCPDF_COVERAGE.md.

TCPDF 6.x codebase

Swap dependency: install compat-legacy

Run existing suite unchanged

Strict-mode audit: enumerate behavioral gaps

Fix call sites: drop ignored params or move to modern API

Re-baseline byte-level test assertions

Remove the TCPDF dependency

Incrementally retire the adapter onto Document

Diagram

Cada etapa mantém a aplicação pronta para entrega. Você nunca precisa fazer uma virada única, de uma só vez.

Instale o nextpdf/compat-legacy (consulte /integrations/tcpdf-compat/install/). Não remova o tecnickcom/tcpdf ainda; manter os dois permite comparar os resultados.

Escolha como os locais de chamada legados devem resolver a classe:

  • Recomendado: altere o use/require de cada arquivo para use NextPDF\Compat\Tcpdf\TCPDF;. Isso é explícito e fácil de pesquisar.
  • Quando você ainda não puder alterar os locais de chamada: habilite os aliases globais opcionais uma vez na inicialização com LegacyBootstrap::enableAliases() (consulte /integrations/tcpdf-compat/boot-and-discovery/). Isso resolve \TCPDF e as quatro classes auxiliares para o adaptador.

As duas estratégias são mutuamente exclusivas na prática. Se a biblioteca real do TCPDF continuar carregável automaticamente e você habilitar os aliases globais, o alias será ignorado quando uma classe \TCPDF já existir. Você pode então continuar usando o TCPDF legado sem perceber. Durante a Etapa 1, prefira importações por arquivo para saber exatamente qual classe cada local de chamada usa. Consulte /integrations/tcpdf-compat/troubleshooting/.

Etapa 2 — Execute a suíte existente sem alterações

Seção intitulada “Etapa 2 — Execute a suíte existente sem alterações”

Execute a suíte de testes completa contra o adaptador sem mudar mais nada. A maioria dos métodos delegados (94 dos ~120 avaliados) se comporta de forma compatível. Espere encontrar duas categorias de falha previsíveis:

  1. Asserções em nível de bytes. Testes que comparam os bytes exatos do Portable Document Format (PDF) vão falhar porque o motor é uma implementação independente. Isso é esperado, não um defeito. Adie esses casos para a Etapa 4.
  2. Ramificações por valor de retorno. Alguns métodos retornam valores de compatibilidade fixos em vez de valores calculados. Em especial, MultiCell() retorna 1, e Write() retorna 0. O código que se ramifica com base nesses valores de retorno precisa de ajuste.

Registre cada falha. Classifique cada uma como baseline de bytes, valor de retorno ou lacuna comportamental real.

Esta etapa torna a migração segura. Execute a suíte ou um fluxo de produção representativo com o modo estrito habilitado:

examples/migration-audit.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;
use NextPDF\Compat\Tcpdf\TCPDF;
function renderInvoice(TCPDF $pdf): void
{
// ... your existing rendering code, unchanged ...
}
$pdf = new TCPDF('P', 'mm', 'A4');
$pdf->setStrictMode(true);
try {
renderInvoice($pdf);
$pdf->Output(__DIR__ . '/audit.pdf', 'F');
} catch (TcpdfNotImplementedException $e) {
// Each message names the method, the ignored parameters, and a hint.
fwrite(STDERR, 'MIGRATION GAP: ' . $e->getMessage() . "\n");
}

Trate cada TcpdfNotImplementedException como um item de trabalho. A mensagem informa o método, a lista exata de parâmetros ignorados e uma dica de migração. O conjunto de métodos que lançam exceções está enumerado e verificado por testes em tests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php. Cada justificativa está em docs/TCPDF_COVERAGE.md.

Execute o modo estrito como um job dedicado de integração contínua (CI), não em produção. O objetivo é revelar lacunas, não fazer a produção disparar exceções.

Para cada lacuna, escolha a correção adequada de menor custo:

Padrão de lacunaCorreção
O parâmetro ignorado não é relevante (e.g. um $align do TCPDF no qual você nunca confiou)Remova o parâmetro. A chamada se torna exatamente compatível.
O parâmetro ignorado era relevante (e.g. um link Image() clicável)Reescreva a chamada com a API moderna. Desenhe a imagem e, em seguida, adicione Document::link() sobre o retângulo.
O método não está implementado (setSignature(), endPage())endPage() / Open(): remova a chamada. Assinatura: consulte /integrations/tcpdf-compat/security-and-operations/; ela requer uma edição comercial.
Método não aplicável (setPDFVersion(), setUserRights())Remova a chamada. A saída é sempre PDF 2.0; user-rights é obsoleto no PDF 2.0.
Ramificação por valor de retornoCalcule o valor você mesmo ou mova essa lógica para a API moderna.

Use a via de escape quando a superfície do TCPDF não conseguir expressar o que você precisa:

examples/migration-escape-hatch.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();
$pdf->AddPage();
// Legacy path stays as-is for the parts that work:
$pdf->SetFont('helvetica', '', 12);
$pdf->Cell(0, 10, 'Header line', 0, 1);
// Modern path for what the TCPDF surface cannot express here:
$document = $pdf->getDocument();
$document->image('logo.png', 10, 30, 40, 0);
$document->link(10, 30, 40, 20, 'https://example.com');

Substitua as asserções de bytes exatos por asserções sobre o que importa:

  • A saída começa com %PDF e pode ser analisada (em nível de smoke test).
  • O conteúdo de texto renderizado está presente (extraia o texto e faça asserções sobre ele).
  • As propriedades estruturais (número de páginas, tamanho da página e presença de um sumário) correspondem.

Esse custo pontual gera testes que sobrevivem a futuras atualizações do motor.

Depois que a auditoria em modo estrito passar, o modo estrito estiver desligado em produção e a suíte estiver verde nas asserções com o baseline redefinido, remova o tecnickcom/tcpdf:

Terminal window
composer remove tecnickcom/tcpdf

Execute a suíte novamente. Se algo ainda for resolvido como a classe TCPDF real, a ressalva sobre aliases da Etapa 1 se aplicou; corrija os locais de chamada restantes para importar o adaptador explicitamente.

O adaptador é um auxílio de migração, não uma camada permanente. Depois que o TCPDF tiver sido removido e o motor estiver validado, aposente o adaptador de forma incremental:

  1. Em cada módulo, substitua new TCPDF(...) pela instanciação moderna de NextPDF\Core\Document.
  2. Substitua as chamadas de método do TCPDF pelos equivalentes modernos (as chamadas a getDocument() que você já adicionou na Etapa 4 são o modelo).
  3. Quando um módulo não referenciar mais o adaptador, exclua suas importações de compatibilidade.
  4. Quando nenhum módulo referenciar o adaptador, remova o nextpdf/compat-legacy do composer.json.

Nesse ponto, você está na API moderna do PDF 2.0 sem nenhuma camada de compatibilidade.

  • nextpdf/compat-legacy instalado; vínculo com o motor verificado.
  • Os locais de chamada importam o adaptador explicitamente (ou aliases habilitados com o TCPDF real removido do caminho de autoload).
  • Suíte completa executada contra o adaptador; falhas classificadas.
  • Job de CI em modo estrito adicionado; cada lacuna catalogada.
  • Cada lacuna corrigida (remover parâmetro / API moderna / remover chamada).
  • Asserções em nível de bytes com o baseline redefinido para conteúdo e estrutura.
  • tecnickcom/tcpdf removido; suíte verde.
  • Adaptador aposentado módulo por módulo; dependência removida.
  • /integrations/tcpdf-compat/method-coverage/ — comportamento por método e orientação de substituição
  • docs/TCPDF_COVERAGE.md — matriz oficial, verificada por testes
  • /integrations/tcpdf-compat/configuration/ — como migrar a configuração para fora das constantes globais
  • /integrations/tcpdf-compat/security-and-operations/ — criptografia e assinatura durante a migração
  • /integrations/tcpdf-compat/troubleshooting/ — o conflito entre alias/real-TCPDF e outras armadilhas