Перейти к содержимому

Диагностика неполадок compat-legacy

Большинство проблем миграции сводится к небольшому набору сценариев. В каждом разделе ниже приведены симптом, причина и способ устранения. Если вы не уверены, как ведёт себя конкретный метод, обратитесь к /integrations/tcpdf-compat/method-coverage/ и авторитетной матрице в репозитории docs/TCPDF_COVERAGE.md.

Раньше процесс останавливался при ошибке PDF, теперь возникает исключение

Заголовок раздела «Раньше процесс останавливался при ошибке PDF, теперь возникает исключение»

Симптом. Код, который раньше останавливался при сбое рендеринга, теперь выбрасывает неперехваченное RuntimeException, а запрос или задание завершается ошибкой.

Причина. В устаревшем TCPDF Error() вызывает die(). Адаптер вместо этого намеренно выбрасывает RuntimeException, чтобы сбои не оставались незамеченными.

Решение. Оберните точки входа рендеринга в try/catch и сопоставьте исключение с вашим контрактом ошибок. Не восстанавливайте поведение die(). См. /integrations/tcpdf-compat/production-usage/ § Обработка сбоев.

new \TCPDF() по-прежнему разрешается в настоящую библиотеку TCPDF

Заголовок раздела «new \TCPDF() по-прежнему разрешается в настоящую библиотеку TCPDF»

Симптом. Вы включили LegacyBootstrap::enableAliases(), но вывод по-прежнему выглядит как в устаревшем TCPDF, либо поведение не изменилось.

Причина. enableAliases() регистрирует псевдоним только тогда, когда класса с таким именем ещё нет. Если tecnickcom/tcpdf остаётся доступным для автозагрузки и его класс \TCPDF загружается первым, псевдоним не создаётся, и ваш код продолжает использовать устаревший TCPDF.

Решение. Во время миграции используйте явные импорты в каждом файле (use NextPDF\Compat\Tcpdf\TCPDF;), чтобы каждое место вызова было однозначным. Удалите tecnickcom/tcpdf после успешного аудита (см. /integrations/tcpdf-compat/migration/ этап 5). Не запускайте обе библиотеки с включёнными глобальными псевдонимами в одном процессе.

Метод «работает», но переданный параметр игнорируется

Заголовок раздела «Метод «работает», но переданный параметр игнорируется»

Симптом. Вызов завершается успешно и создаёт файл в формате Portable Document Format (PDF), но переданный вами параметр (ссылка изображения, выравнивание, точек на дюйм (DPI), цвет закладки, …) ни на что не влияет.

Причина. Метод входит в набор тихо игнорируемых. Он принимает параметр ради совместимости исходного кода, а затем отбрасывает его. Это задокументированное поведение, а не ошибка; см. /integrations/tcpdf-compat/method-coverage/ §2.

Решение. Запустите аудит в строгом режиме, чтобы найти каждый такой вызов:

examples/troubleshoot-strict.php
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use NextPDF\Compat\Tcpdf\Exception\TcpdfNotImplementedException;
use NextPDF\Compat\Tcpdf\TCPDF;
$pdf = new TCPDF();
$pdf->setStrictMode(true);
$pdf->AddPage();
$pdf->SetFont('helvetica', '', 12);
try {
$pdf->Image('logo.png', 10, 10, 50, 0, '', 'https://example.com');
} catch (TcpdfNotImplementedException $e) {
// Message lists every ignored parameter and a migration hint.
echo $e->getMessage(), "\n";
}

Затем удалите параметр или выразите его через современный API ($pdf->getDocument()), как показано в /integrations/tcpdf-compat/migration/ этап 4.

Симптом. Код, который ветвится по возвращаемому значению MultiCell() (например, чтобы вычислить занятую высоту или количество строк), работает неправильно.

Причина. MultiCell() в адаптере возвращает заглушку совместимости 1, а не фактическое количество отрисованных ячеек или строк. Write() аналогично возвращает 0.

Решение. Не ветвите код по этим возвращаемым значениям. Если вам нужна высота отрисованного блока, вычислите её через getStringHeight() / getNumLines() или перенесите эту логику в современный API.

Симптом. Вы запросили более раннюю версию PDF; на выходе по-прежнему PDF 2.0.

Причина. Адаптер всегда выводит PDF 2.0 (ISO 32000-2). setPDFVersion() входит в набор неприменимых методов: адаптер выдаёт уведомление и продолжает работу.

Решение. Удалите вызов. Если следующему потребителю по цепочке нужна более ранняя версия PDF, обрабатывайте это требование отдельно; адаптер не может понижать целевую версию.

Симптом. Вы вызвали setSignature() с сертификатом; в итоговом PDF подписи нет.

Причина. Базовый движок не реализует setSignature() через этот адаптер. В режиме по умолчанию это безоперационный вызов; в строгом режиме он выбрасывает исключение.

Решение. Для подписания требуется коммерческая редакция NextPDF и современный API подписи. См. /integrations/tcpdf-compat/security-and-operations/ § Цифровые подписи. Не рассчитывайте, что устаревший вызов setSignature() что-либо подпишет.

Output() испортил мой HTTP-ответ или вывод обработчика

Заголовок раздела «Output() испортил мой HTTP-ответ или вывод обработчика»

Симптом. Байты PDF появляются в ответе Hypertext Transfer Protocol (HTTP), либо журнал обработчика заполняется байтами PDF.

Причина. Вы использовали назначение вывода, которое пишет в выходной поток (I/D), хотя ответом управляете вы сами. Адаптер не выводит данные в ваш буфер так, как это делает устаревший TCPDF, но I/D по-прежнему запускают вывод движка.

Решение. В обработчиках и воркерах, которыми вы управляете, используйте Output($path, 'F'), чтобы записать файл, или Output($name, 'S'), чтобы получить байты и вывести их самостоятельно. tests/Unit/Compat/Tcpdf/Bridge/OutputBridgeTest.php проверяет, что сопоставление назначений не зависит от регистра и внешних пробелов:

КодВозвращаетПобочный эффект
Sбайты PDF (%PDF…)нет
Fпустая строказаписывает файл
Eтело MIME в base64нет
FI / FDпустая строказаписывает файл, затем вывод движка
I / D / неизвестнопустая строкавывод движка (встроенный/скачивание)

Побайтовые проверки PDF не проходят после перехода

Заголовок раздела «Побайтовые проверки PDF не проходят после перехода»

Симптом. Снимочные тесты, сравнивающие сырые байты PDF, массово не проходят.

Причина. Движок использует независимую реализацию PDF 2.0. Делегированные методы дают совместимый видимый результат, но байты отличаются. Это ожидаемое поведение.

Решение. Перестройте эталоны тестов так, чтобы проверять отрисованное содержимое (извлечённый текст), структуру (число страниц, размер страницы) или базовый smoke check (str_starts_with($bytes, '%PDF')). См. /integrations/tcpdf-compat/migration/ этап 4.

Устаревшая константа K_* / PDF_* имеет неверное значение

Заголовок раздела «Устаревшая константа K_* / PDF_* имеет неверное значение»

Симптом. Пользовательский путь или значение по умолчанию, заданное через константу, не применяется.

Причина. Адаптер автоматически определяет константу только в том случае, если она ещё не определена, и делает это при первом создании экземпляра. Если ваш define() выполняется после создания первого адаптера, уже действует значение по умолчанию из адаптера.

Решение. Определяйте каждую пользовательскую константу K_* / PDF_* в вашем bootstrap до создания любого экземпляра адаптера. См. /integrations/tcpdf-compat/configuration/ § Порядок разрешения конфигурации.

Несоответствие версии движка при создании экземпляра

Заголовок раздела «Несоответствие версии движка при создании экземпляра»

Симптом. Создание экземпляра завершается сбоем или поведение неожиданно меняется после обновления зависимости.

Причина. Адаптер требует nextpdf/core ^3.0. Разрешённая версия core вне этого диапазона не поддерживается.

Решение. Выполните composer show nextpdf/core и закрепите движок на ^3.0. См. /integrations/tcpdf-compat/install/ § Проверка версии движка.

ВопросГде искать
Что метод X действительно здесь делает?Справочник: /integrations/tcpdf-compat/method-coverage/, docs/TCPDF_COVERAGE.md
Какие из моих вызовов теряют параметры?Аудит в строгом режиме (эта страница; /integrations/tcpdf-compat/migration/)
Почему процесс не остановился при ошибке?/integrations/tcpdf-compat/security-and-operations/ § Усиленные модели поведения
Почему вывод не подписан / не PDF/A?Раздел /integrations/tcpdf-compat/security-and-operations/
Конфликт псевдонима и явного импортаЭта страница; /integrations/tcpdf-compat/boot-and-discovery/
  • /integrations/tcpdf-compat/migration/ — поэтапная миграция, которая предотвращает большинство перечисленных выше проблем
  • /integrations/tcpdf-compat/method-coverage/ — справочник по поведению каждого метода
  • /integrations/tcpdf-compat/boot-and-discovery/ — регистрация псевдонимов и предотвращение конфликтов
  • docs/TCPDF_COVERAGE.md — авторитетная матрица покрытия