Переход с TCPDF 6.x на NextPDF
Переходите в чёткой последовательности. Сначала переведите проект на движок NextPDF с минимально возможными изменениями. Зафиксируйте, что уже работает. Проверьте, что не работает. Исправьте каждое место вызова. Затем удалите адаптер. Слой совместимости поддерживает этапы со второго по четвёртый; он не является конечной целью.
На этой странице описана стратегия. Точное поведение конкретного метода смотрите в /integrations/tcpdf-compat/method-coverage/ и в авторитетной матрице репозитория docs/TCPDF_COVERAGE.md.
Модель перехода
Заголовок раздела «Модель перехода»На каждом этапе приложение остаётся готовым к выпуску. Полный одномоментный переход никогда не требуется.
Этап 1 — замена зависимости
Заголовок раздела «Этап 1 — замена зависимости»Установите nextpdf/compat-legacy (см. /integrations/tcpdf-compat/install/). Пока не удаляйте tecnickcom/tcpdf: наличие обоих пакетов позволяет сравнивать результаты.
Выберите, как унаследованные места вызова должны разрешать класс:
- Предпочтительно: в каждом файле замените текущий
use/requireнаuse NextPDF\Compat\Tcpdf\TCPDF;. Это явный подход, его легко найти поиском. - Если пока нельзя изменять места вызова: один раз при загрузке включите необязательные глобальные псевдонимы с помощью
LegacyBootstrap::enableAliases()(см. /integrations/tcpdf-compat/boot-and-discovery/). При этом\TCPDFи четыре вспомогательных класса будут разрешаться как классы адаптера.
На практике эти две стратегии взаимоисключающи. Если реальная библиотека TCPDF остаётся доступной для автозагрузки и вы включаете глобальные псевдонимы, псевдоним не создаётся, если класс
\TCPDFуже существует. В таком случае вы можете незаметно продолжить использовать устаревший TCPDF. На этапе 1 отдавайте предпочтение импортам в отдельных файлах, чтобы точно знать, какой класс использует каждое место вызова. См. /integrations/tcpdf-compat/troubleshooting/.
Этап 2 — запуск существующего набора тестов без изменений
Заголовок раздела «Этап 2 — запуск существующего набора тестов без изменений»Запустите полный набор тестов с адаптером, не меняя ничего другого. Большинство делегированных методов (94 из ~120 рассмотренных) ведут себя совместимо. Ожидайте два предсказуемых типа сбоев:
- Проверки на уровне байтов. Тесты, которые сравнивают точные байты формата Portable Document Format (PDF), завершатся неудачей, поскольку движок — независимая реализация. Это ожидаемо и не является дефектом. Отложите их до этапа 4.
- Ветвление по возвращаемым значениям. Некоторые методы возвращают совместимые заглушки вместо вычисленных значений. В частности,
MultiCell()возвращает1, аWrite()—0. Код, который ветвится по этим возвращаемым значениям, нужно скорректировать.
Занесите каждый сбой в каталог. Классифицируйте его как байтовый эталон, возвращаемое значение или настоящий пробел в поведении.
Этап 3 — аудит в строгом режиме
Заголовок раздела «Этап 3 — аудит в строгом режиме»Этот этап делает переход безопасным. Запустите набор тестов или репрезентативный рабочий сценарий с включённым строгим режимом:
<?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");}Рассматривайте каждое исключение TcpdfNotImplementedException как отдельную задачу. Сообщение указывает метод, точный список игнорируемых параметров и подсказку по переходу. Методы, которые выбрасывают исключения, перечислены и проверены тестами в tests/Unit/Compat/Tcpdf/TcpdfStrictModeTest.php. Обоснование каждого случая приведено в docs/TCPDF_COVERAGE.md.
Запускайте строгий режим как отдельную задачу непрерывной интеграции (CI), а не в производственной среде. Цель — выявить пробелы, а не заставить производственную среду выбрасывать исключения.
Этап 4 — исправление мест вызова
Заголовок раздела «Этап 4 — исправление мест вызова»Для каждого пробела выбирайте самое простое корректное исправление:
| Тип пробела | Исправление |
|---|---|
Игнорируемый параметр не имеет значения (например, параметр $align в TCPDF, на который вы никогда не полагались) | Удалите параметр. Вызов становится совместимым (не byte-identical). |
Игнорируемый параметр имел значение (например, кликабельная ссылка Image()) | Перепишите участок с помощью современного API. Нарисуйте изображение, затем добавьте Document::link() поверх прямоугольника. |
Метод не реализован (setSignature(), endPage()) | endPage() / Open(): удалите вызов. Подписание: см. /integrations/tcpdf-compat/security-and-operations/; для него требуется коммерческая редакция. |
Неприменимый метод (setPDFVersion(), setUserRights()) | Удалите вызов. Вывод всегда соответствует PDF 2.0; права пользователя считаются устаревшими в PDF 2.0. |
| Ветвление по возвращаемому значению | Вычислите значение самостоятельно или перенесите эту логику в современный API. |
Используйте обходной путь, когда интерфейс TCPDF не позволяет выразить нужное:
<?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');Переустановка эталонов для тестов на уровне байтов
Заголовок раздела «Переустановка эталонов для тестов на уровне байтов»Замените проверки точных байтов проверками того, что действительно важно:
- Вывод начинается с
%PDFи поддаётся разбору (smoke-тест). - Отрисованный текст присутствует (извлеките текст и проверьте его).
- Структурные свойства (количество страниц, размер страницы и наличие закладок) совпадают.
Эта разовая работа даст вам тесты, которые останутся работоспособными при будущих обновлениях движка.
Этап 5 — удаление зависимости от TCPDF
Заголовок раздела «Этап 5 — удаление зависимости от TCPDF»После того как аудит в строгом режиме пройден, строгий режим отключён в производственной среде, а набор тестов проходит с обновлёнными эталонными проверками, удалите tecnickcom/tcpdf:
composer remove tecnickcom/tcpdfЗапустите набор тестов снова. Если что-либо по-прежнему разрешается в реальный класс TCPDF, сработала оговорка о псевдонимах из этапа 1; исправьте оставшиеся места вызова, чтобы они явно импортировали адаптер.
Этап 6 — отказ от адаптера
Заголовок раздела «Этап 6 — отказ от адаптера»Адаптер — средство перехода, а не постоянный слой. После того как TCPDF удалён, а движок проверен, постепенно отказывайтесь от адаптера:
- В каждом модуле замените
new TCPDF(...)созданием современногоNextPDF\Core\Document. - Замените вызовы методов TCPDF современными эквивалентами (ориентируйтесь на вызовы
getDocument(), которые вы уже добавили на этапе 4). - Когда модуль больше не ссылается на адаптер, удалите его импорты совместимости.
- Когда ни один модуль не ссылается на адаптер, удалите
nextpdf/compat-legacyизcomposer.json.
На этом этапе вы работаете с современным API PDF 2.0 без слоя совместимости.
Контрольный список перехода
Заголовок раздела «Контрольный список перехода»-
nextpdf/compat-legacyустановлен; интеграция с движком проверена. - Места вызова явно импортируют адаптер (либо включены псевдонимы, а настоящий TCPDF удалён из пути автозагрузки).
- Полный набор тестов запущен с адаптером; сбои классифицированы.
- Добавлена CI-задача для строгого режима; каждый пробел внесён в каталог.
- Каждый пробел исправлен (удаление параметра / современный API / удаление вызова).
- Проверки на уровне байтов перенастроены на содержимое и структуру.
-
tecnickcom/tcpdfудалён; набор тестов проходит успешно. - Отказ от адаптера выполнен модуль за модулем; зависимость удалена.
См. также
Заголовок раздела «См. также»- /integrations/tcpdf-compat/method-coverage/ — поведение каждого метода и рекомендации по замене
docs/TCPDF_COVERAGE.md— эталонная матрица, проверенная тестами- /integrations/tcpdf-compat/configuration/ — перенос конфигурации из глобальных констант
- /integrations/tcpdf-compat/security-and-operations/ — шифрование и подписание во время перехода
- /integrations/tcpdf-compat/troubleshooting/ — конфликт alias/real-TCPDF и другие ловушки