Przejdź do głównej zawartości

Migracja z TCPDF 6.x do NextPDF

Migruj w jasnej kolejności. Najpierw przejdź na silnik NextPDF przy możliwie najmniejszej zmianie. Potwierdź, co już działa. Przeprowadź audyt tego, co nie działa. Napraw każde miejsce wywołania. Następnie usuń adapter. Warstwa zgodności obsługuje kroki od drugiego do czwartego; nie jest rozwiązaniem docelowym.

Ta strona opisuje strategię. Dokładne zachowanie konkretnej metody sprawdzaj w /integrations/tcpdf-compat/method-coverage/ oraz w miarodajnej macierzy w repozytorium 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

Na każdym etapie aplikacja pozostaje gotowa do wdrożenia. Nigdy nie trzeba przełączać wszystkiego naraz.

Zainstaluj nextpdf/compat-legacy (zobacz /integrations/tcpdf-compat/install/). Nie usuwaj jeszcze tecnickcom/tcpdf; pozostawienie obu zależności pozwala porównywać wyniki.

Wybierz sposób rozwiązywania klasy w starszych miejscach wywołań:

  • Zalecane: w każdym pliku zmień use/require na use NextPDF\Compat\Tcpdf\TCPDF;. Jest to jednoznaczne i łatwe do wyszukania.
  • Gdy nie możesz jeszcze modyfikować miejsc wywołań: włącz raz podczas startu opcjonalne aliasy globalne za pomocą LegacyBootstrap::enableAliases() (zobacz /integrations/tcpdf-compat/boot-and-discovery/). Dzięki temu \TCPDF oraz cztery klasy pomocnicze będą rozwiązywane do adaptera.

W praktyce obie strategie wzajemnie się wykluczają. Jeśli prawdziwa biblioteka TCPDF nadal jest dostępna dla autoloadera, a włączysz aliasy globalne, alias zostanie pominięty, gdy klasa \TCPDF już istnieje. Możesz wtedy nadal nieświadomie korzystać ze starszej biblioteki TCPDF. Na etapie 1 preferuj importy w poszczególnych plikach, aby dokładnie wiedzieć, której klasy używa każde miejsce wywołania. Zobacz /integrations/tcpdf-compat/troubleshooting/.

Etap 2 — Uruchom istniejący zestaw testów bez zmian

Dział zatytułowany „Etap 2 — Uruchom istniejący zestaw testów bez zmian”

Uruchom pełny zestaw testów z adapterem, nie zmieniając niczego innego. Większość delegowanych metod (94 z około 120 przebadanych) zachowuje zgodność. Spodziewaj się dwóch przewidywalnych kategorii niepowodzeń:

  1. Asercje na poziomie bajtów. Testy porównujące dokładne bajty formatu Portable Document Format (PDF) zakończą się niepowodzeniem, ponieważ silnik jest niezależną implementacją. Jest to zachowanie oczekiwane, a nie usterka. Odłóż je do etapu 4.
  2. Rozgałęzienia oparte na wartościach zwracanych. Kilka metod zwraca wartości zastępcze zapewniające zgodność, a nie wartości obliczone. W szczególności MultiCell() zwraca 1, a Write() zwraca 0. Kod, który rozgałęzia się na podstawie tych wartości zwracanych, wymaga dostosowania.

Skataloguj każde niepowodzenie i sklasyfikuj je jako byte-baseline, return-value lub true behavioral gap.

Ten etap zabezpiecza migrację. Uruchom zestaw testów lub reprezentatywny przepływ produkcyjny z włączonym trybem ścisłym:

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

Traktuj każdy wyjątek TcpdfNotImplementedException jako osobne zadanie. Komunikat podaje metodę, dokładną listę pominiętych parametrów oraz wskazówkę dotyczącą migracji. Zestaw metod zgłaszających wyjątki jest jawnie wymieniony i potwierdzony asercjami testowymi w tests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php. Uzasadnienie każdej pozycji znajduje się w docs/TCPDF_COVERAGE.md.

Uruchamiaj tryb ścisły jako dedykowane zadanie ciągłej integracji (CI), a nie w środowisku produkcyjnym. Chodzi o ujawnienie luk, a nie o to, by środowisko produkcyjne zgłaszało wyjątki.

Dla każdej luki wybierz najmniej kosztowne poprawne rozwiązanie:

Wzorzec lukiPoprawka
Pominięty parametr nie ma znaczenia (np. parametr $align z TCPDF, od którego kod nigdy nie zależał)Usuń parametr. Wywołanie staje się w pełni zgodne.
Pominięty parametr miał znaczenie (np. klikalny odnośnik Image())Odwzoruj to za pomocą nowoczesnego API. Narysuj obraz, a następnie dodaj Document::link() na prostokącie.
Metoda nie jest zaimplementowana (setSignature(), endPage())endPage() / Open(): usuń wywołanie. Podpisywanie: zobacz /integrations/tcpdf-compat/security-and-operations/; wymaga edycji komercyjnej.
Metoda niemająca zastosowania (setPDFVersion(), setUserRights())Usuń wywołanie. Dane wyjściowe są zawsze w formacie PDF 2.0; uprawnienia użytkownika są wycofane w PDF 2.0.
Rozgałęzienie oparte na wartości zwracanejOblicz wartość samodzielnie lub przenieś tę logikę do nowoczesnego API.

Skorzystaj z furtki awaryjnej, gdy interfejs TCPDF nie pozwala wyrazić wymaganego zachowania:

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

Zastąp asercje dokładnych bajtów asercjami obejmującymi to, co istotne:

  • Dane wyjściowe zaczynają się od %PDF i dają się parsować (poziom smoke).
  • Wyrenderowana treść tekstowa jest obecna (wyodrębnij tekst i sprawdź go asercją).
  • Właściwości strukturalne (liczba stron, rozmiar strony oraz obecność konspektu) są zgodne.

Ten jednorazowy koszt pozwala uzyskać testy, które przetrwają przyszłe aktualizacje silnika.

Gdy audyt w trybie ścisłym przejdzie pomyślnie, tryb ścisły jest wyłączony w środowisku produkcyjnym, a zestaw testów jest zielony na nowo ustalonych asercjach, usuń tecnickcom/tcpdf:

Okno terminala
composer remove tecnickcom/tcpdf

Uruchom zestaw testów ponownie. Jeśli cokolwiek nadal rozwiązuje się do prawdziwej klasy TCPDF, potwierdziło się zastrzeżenie dotyczące aliasów z etapu 1; popraw pozostałe miejsca wywołań, aby jawnie importowały adapter.

Adapter jest pomocą w migracji, a nie trwałą warstwą. Gdy TCPDF zostanie usunięty, a działanie silnika potwierdzone, wycofuj adapter stopniowo:

  1. W każdym module zastąp new TCPDF(...) nowoczesną konstrukcją NextPDF\Core\Document.
  2. Zastąp wywołania metod TCPDF ich nowoczesnymi odpowiednikami (wzorem są wywołania getDocument(), które dodałeś już na etapie 4).
  3. Gdy moduł nie odwołuje się już do adaptera, usuń jego importy warstwy zgodności.
  4. Gdy żaden moduł nie odwołuje się do adaptera, usuń nextpdf/compat-legacy z composer.json.

Od tego momentu korzystasz z nowoczesnego API PDF 2.0 bez warstwy zgodności.

  • nextpdf/compat-legacy zainstalowany; integracja z silnikiem zweryfikowana.
  • Miejsca wywołań jawnie importują adapter (lub aliasy są włączone, a prawdziwy TCPDF usunięty ze ścieżki automatycznego ładowania).
  • Pełny zestaw testów uruchomiony na adapterze; niepowodzenia sklasyfikowane.
  • Dodane zadanie CI w trybie ścisłym; każda luka skatalogowana.
  • Każda luka naprawiona (usunięcie parametru / nowoczesne API / usunięcie wywołania).
  • Asercje na poziomie bajtów przeniesione na nową bazę opartą na treści i strukturze.
  • tecnickcom/tcpdf usunięty; zestaw testów zielony.
  • Adapter wycofany moduł po module; zależność usunięta.
  • /integrations/tcpdf-compat/method-coverage/ — zachowanie poszczególnych metod i wskazówki dotyczące zamienników
  • docs/TCPDF_COVERAGE.md — miarodajna, zweryfikowana testami macierz
  • /integrations/tcpdf-compat/configuration/ — przeniesienie konfiguracji ze stałych globalnych
  • /integrations/tcpdf-compat/security-and-operations/ — szyfrowanie i podpisywanie podczas migracji
  • /integrations/tcpdf-compat/troubleshooting/ — konflikt alias/real-TCPDF i inne pułapki