Salta ai contenuti

Migrare da TCPDF 6.x a NextPDF

La migrazione segue una sequenza precisa. Passare prima al motore NextPDF, con la modifica più piccola possibile. Verificare ciò che funziona già. Sottoporre ad audit ciò che non funziona. Correggere i punti di chiamata uno alla volta. Solo dopo rimuovere l’adattatore. Il livello di compatibilità supporta i passi dal due al quattro; non è la destinazione finale.

Questa pagina descrive la strategia. Per il comportamento esatto di un singolo metodo, usare /integrations/tcpdf-compat/method-coverage/ insieme alla matrice autorevole nel repository 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

Ogni fase mantiene l’applicazione distribuibile. Non serve mai un unico passaggio in blocco.

Installare nextpdf/compat-legacy (vedere /integrations/tcpdf-compat/install/). Non rimuovere ancora tecnickcom/tcpdf — mantenere entrambi consente di eseguire confronti.

Scegliere come i punti di chiamata legacy risolvono la classe:

  • Preferito: modificare use/require in use NextPDF\Compat\Tcpdf\TCPDF; per ciascun file. È esplicito e facile da ricercare con grep.
  • Quando non si possono ancora toccare i punti di chiamata: abilitare una volta all’avvio gli alias globali opt-in con LegacyBootstrap::enableAliases() (vedere /integrations/tcpdf-compat/boot-and-discovery/). In questo modo \TCPDF e le quattro classi di supporto vengono risolte sull’adattatore.

Le due strategie sono in pratica mutuamente esclusive. Se la libreria TCPDF reale è ancora caricabile automaticamente e si abilitano gli alias globali, l’alias viene saltato quando una classe \TCPDF esiste già. Si rischia quindi di continuare a usare silenziosamente la TCPDF legacy. Durante la Fase 1, preferire gli import per singolo file, così da sapere esattamente quale classe usa ogni punto di chiamata. Vedere /integrations/tcpdf-compat/troubleshooting/.

Fase 2 — Eseguire la suite esistente senza modifiche

Sezione intitolata “Fase 2 — Eseguire la suite esistente senza modifiche”

Eseguire l’intera suite di test sull’adattatore senza altre modifiche al codice. La maggior parte dei metodi delegati (94 dei circa 120 esaminati) si comporta in modo compatibile. Aspettarsi due classi di fallimenti prevedibili:

  1. Asserzioni a livello di byte. I test che confrontano i byte esatti del PDF falliranno perché il motore è un’implementazione indipendente. È un comportamento previsto, non un difetto. Rinviarli alla Fase 4.
  2. Diramazioni sul valore di ritorno. Alcuni metodi restituiscono segnaposto di compatibilità anziché valori calcolati — in particolare MultiCell() restituisce 1 e Write() restituisce 0. Il codice che si dirama su tali valori di ritorno richiede un adeguamento.

Catalogare ogni fallimento. Classificare ciascuno come byte-baseline, return-value oppure divario comportamentale effettivo.

Questa è la fase che rende sicura la migrazione. Eseguire la suite (o un percorso di produzione rappresentativo) con la modalità strict abilitata:

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");
}

Ogni TcpdfNotImplementedException è un elemento di lavoro. Il messaggio contiene il metodo, l’elenco esatto dei parametri ignorati e un suggerimento di migrazione. L’insieme dei metodi che sollevano l’eccezione è elencato e verificato dai test in tests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php. La motivazione di ciascuno si trova in docs/TCPDF_COVERAGE.md.

Eseguire la modalità strict come job CI dedicato, non in produzione. Lo scopo è far emergere i divari, non generare eccezioni in produzione.

Per ogni divario, scegliere la correzione corretta meno onerosa:

Schema del divarioCorrezione
Il parametro ignorato non ha importanza (e.g. un $align di TCPDF su cui non si è mai fatto affidamento)Eliminare il parametro. La chiamata diventa pienamente compatibile.
Il parametro ignorato aveva importanza (e.g. un collegamento cliccabile su Image())Riesprimerlo tramite l’API moderna. Disegnare l’immagine, quindi aggiungere Document::link() sopra il rettangolo.
Il metodo non è implementato (setSignature(), endPage())endPage() / Open(): rimuovere la chiamata. Firma: vedere /integrations/tcpdf-compat/security-and-operations/ — richiede un’edizione commerciale.
Metodo non applicabile (setPDFVersion(), setUserRights())Rimuovere. L’output è sempre PDF 2.0; i diritti utente sono deprecati in PDF 2.0.
Diramazione sul valore di ritornoCalcolare il valore autonomamente, oppure spostare quella logica nell’API moderna.

Usare la via di fuga per tutto ciò che la superficie di TCPDF non può esprimere:

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');

Sostituire le asserzioni sui byte esatti con asserzioni su ciò che conta davvero:

  • L’output inizia con %PDF e viene analizzato correttamente (livello smoke).
  • Il contenuto testuale renderizzato è presente (estrarre il testo ed eseguire lì le asserzioni).
  • Le proprietà strutturali (numero di pagine, dimensione della pagina, presenza di una struttura) corrispondono.

È un costo una tantum e produce test capaci di sopravvivere ai futuri aggiornamenti del motore.

Quando l’audit in modalità strict supera i controlli, con la modalità strict disattivata in produzione, e la suite è verde sulle asserzioni ricalibrate, rimuovere tecnickcom/tcpdf:

Terminal window
composer remove tecnickcom/tcpdf

Rieseguire la suite. Se qualcosa si risolve ancora nella classe TCPDF reale, vale l’avvertenza sugli alias della Fase 1 — correggere i punti di chiamata rimanenti affinché importino esplicitamente l’adattatore.

L’adattatore è un ausilio alla migrazione, non un livello permanente. Una volta eliminato TCPDF e collaudato il motore, dismettere l’adattatore in modo incrementale:

  1. In ciascun modulo, sostituire new TCPDF(...) con la costruzione moderna NextPDF\Core\Document.
  2. Sostituire le chiamate ai metodi TCPDF con i loro equivalenti moderni (le chiamate getDocument() già aggiunte nella Fase 4 sono il modello).
  3. Quando un modulo non fa più riferimento all’adattatore, eliminarne gli import di compatibilità.
  4. Quando nessun modulo fa riferimento all’adattatore, rimuovere nextpdf/compat-legacy da composer.json.

A quel punto si usa l’API moderna PDF 2.0 senza alcun livello di compatibilità.

  • nextpdf/compat-legacy installato; collegamento al motore verificato.
  • I punti di chiamata importano esplicitamente l’adattatore (oppure gli alias sono abilitati con la TCPDF reale rimossa dal percorso di autoload).
  • Suite completa eseguita sull’adattatore; fallimenti classificati.
  • Job CI in modalità strict aggiunto; ogni divario catalogato.
  • Ogni divario corretto (eliminare il parametro / API moderna / rimuovere la chiamata).
  • Asserzioni a livello di byte ricalibrate su content/structure.
  • tecnickcom/tcpdf rimosso; suite verde.
  • Adattatore dismesso modulo per modulo; dipendenza rimossa.
  • /integrations/tcpdf-compat/method-coverage/ — comportamento per metodo e indicazioni di sostituzione
  • docs/TCPDF_COVERAGE.md — matrice autorevole, verificata dai test
  • /integrations/tcpdf-compat/configuration/ — spostamento della configurazione dalle costanti globali
  • /integrations/tcpdf-compat/security-and-operations/ — cifratura e firma durante la migrazione
  • /integrations/tcpdf-compat/troubleshooting/ — il conflitto alias/real-TCPDF e altre insidie