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

Переход с Dompdf на NextPDF

Это руководство помогает перенести кодовую базу на основе Dompdf, которая генерирует файлы Portable Document Format (PDF) из Hypertext Markup Language (HTML), на конвейер NextPDF Html. Большинство мест вызова переносятся механически, потому что обе библиотеки следуют одному процессу: загрузить HTML, отрисовать его и выдать PDF. Основная работа сводится к карте параметров и различиям в поддержке Cascading Style Sheets (CSS). NextPDF и Dompdf — независимые движки, поэтому макет, созданный Dompdf, совместим с выводом NextPDF, но не идентичен ему побайтово. Это руководство охватывает сопоставление методов, сопоставление ключей параметров, различия в поведении и безопасную последовательность перехода.

Поддержка функции HTML/CSS в NextPDF не гарантирует, что документ Dompdf воспроизводится попиксельно. Матрица поддержки CSS — главный источник сведений о проверенных функциях. Это руководство описывает поведение и не заявляет о визуальной эквивалентности.

Окно терминала
composer require nextpdf/core:^3

Оставьте dompdf/dompdf установленным на время перехода. Последовательность безопасного перехода запускает оба движка параллельно, пока каждое место вызова не будет переключено. Удалите пакет после завершения переключения.

Объект Dompdf в Dompdf — это единый фасад, который владеет Document Object Model (DOM), таблицей стилей, деревом фреймов и холстом. NextPDF разделяет эти задачи: NextPDF\Core\Document владеет моделью страниц и выводом, а writeHtml() управляет конвейером HTML. Отдельной двухэтапной фазы “отрисовать, затем вывести” нет. writeHtml() размещает содержимое по мере записи, а PDF выдаётся с помощью save(), output() или getPdfData().

Содержимое страницы, которое записывает NextPDF, — это результат отрисовки потока содержимого ISO 32000-2 (ISO 32000-2 §8, iso32000_2_sec8#x1.x3.p14). Геометрия страницы, управляемая параметром размера бумаги, сопоставляется с MediaBox объекта страницы (ISO 32000-2 §7, iso32000_2_sec7#x1.x104.p10). Это фундаментальные свойства движка, общие для любого средства записи, соответствующего стандарту. Алгоритм компоновки, который превращает CSS в это содержимое, принадлежит NextPDF и отличается от алгоритма Dompdf; см. Различия в поведении.

Интерфейс прикладного программирования (API) NextPDF Html описан в справочнике Модуль Html, который автоматически генерируется из PHPDoc. Используемые далее точки входа — Document::createStandalone(), Document::writeHtml(string $html): static, Document::writeHtmlCell(...), Document::output(?string, OutputDestination), Document::save(string $path): void, Document::getPdfData(): string, а также объект-значение NextPDF\Core\Config (pageSize, margins, fontsDirectory).

Имена публичного API Dompdf, приведённые ниже, сверены с публичным upstream-репозиторием (dompdf/dompdf, master); см. файл происхождения в репозитории _source-sidecar-upstream-api.md. Текст upstream-документации не воспроизводится.

DompdfNextPDFПримечания
new Dompdf($options)Document::createStandalone($config)Dompdf принимает объект Options; NextPDF принимает NextPDF\Core\Config. Используйте DocumentFactory для долгоживущих обработчиков вместо createStandalone().
$dompdf->loadHtml($html, $encoding)$doc->writeHtml($html)NextPDF обрабатывает входные данные как UTF-8. Перекодируйте входные данные, отличные от UTF-8, до вызова, а не передавайте аргумент кодировки.
$dompdf->loadHtmlFile($file)$doc->writeHtml(file_get_contents($file))NextPDF не имеет варианта загрузки из файла. Читайте файл самостоятельно, чтобы политика работы с ресурсами осталась в вашем коде.
$dompdf->setPaper($size, $orientation)ConfigpageSize (объект-значение PageSize)См. карту параметров.
$dompdf->render()(неявно)NextPDF выполняет компоновку во время writeHtml(); отдельной фазы отрисовки нет. Удалите вызов render().
$dompdf->output()$doc->getPdfData()Возвращает байты PDF.
$dompdf->stream($name, $opts)$doc->output($name, OutputDestination::Download)NextPDF выбирает назначение с помощью перечисления OutputDestination.
$dompdf->setBasePath($p) / setProtocol() / setBaseHost()(разрешение ресурсов отличается)NextPDF разрешает относительные ресурсы относительно рабочего набора документа, а не тройки path/protocol/хост; см. Различия в поведении.
$dompdf->addInfo($label, $value)$doc->setTitle() / setAuthor() / API метаданныхПроизвольные пары сведений Dompdf сопоставляются с типизированными сеттерами метаданных (ISO 32000-2 §14, сведения о документе, iso32000_2_sec14#x1.x5.p5).
$dompdf->setHttpContext($ctx)(нет эквивалента)NextPDF не извлекает удалённые ресурсы через контекст потока; см. Не поддерживается / нет прямого эквивалента.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// Dompdf:
// $dompdf = new Dompdf();
// $dompdf->loadHtml('<h1>Invoice</h1>');
// $dompdf->setPaper('A4', 'portrait');
// $dompdf->render();
// file_put_contents('out.pdf', $dompdf->output());
// NextPDF — the createStandalone() default page size is A4 portrait:
$doc = Document::createStandalone();
$doc->setTitle('Invoice');
$doc->addPage();
$doc->writeHtml('<h1>Invoice</h1>');
$doc->save(__DIR__ . '/out.pdf');
echo "Wrote out.pdf\n";

Ниже повторяется examples/08-html-basic.php — исполняемая основа этого руководства, но с явным размером бумаги, отличным от значения по умолчанию, и полями. Пример соответствует вызову setPaper() в Dompdf плюс настройке полей через Options.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Contracts\OutputDestination;
use NextPDF\Core\Config;
use NextPDF\Core\Document;
use NextPDF\ValueObjects\Margin;
use NextPDF\ValueObjects\PageSize;
// Equivalent of: $dompdf->setPaper('letter','portrait') + margin options.
// US Letter portrait = 612 x 792 pt.
// Margin constructor order is (top, right, bottom, left) — all 0.5in here.
$config = new Config(
pageSize: new PageSize(612.0, 792.0, 'Letter'),
margins: new Margin(36.0, 36.0, 36.0, 36.0), // top,right,bottom,left; 0.5in in points
);
$doc = Document::createStandalone($config);
$doc->setTitle('Quarterly Report');
$doc->setAuthor('Finance');
$doc->addPage();
$html = <<<'HTML'
<h1 style="color:#1E3A8A;">Quarterly Report</h1>
<p>This report renders through the NextPDF Html pipeline. The CSS subset that
is <strong>Verified</strong> for production is the support-matrix authority,
not this page.</p>
<table border="1">
<tr><th>Region</th><th>Total</th></tr>
<tr><td>EMEA</td><td>1,204</td></tr>
</table>
HTML;
$doc->writeHtml($html);
// Equivalent of $dompdf->stream('report.pdf'):
$doc->output('report.pdf', OutputDestination::Download);
  • Нет двухфазной отрисовки. Код Dompdf, который проверяет состояние между render() и output(), например читает количество страниц, не имеет аналога в NextPDF в этой конкретной точке. Опрашивайте документ после writeHtml().
  • Кодировка. NextPDF не использует параметр $encoding из Dompdf. Преобразуйте входные данные в UTF-8 перед writeHtml(). Передача байтов Latin-1 приводит к искажению символов, а не к ошибке.
  • render(), оставленный на месте. Оставшийся вызов вида $dompdf->render() не имеет метода в NextPDF и завершается фатальной ошибкой “undefined method”. Удалите его во время переключения; не заглушайте его.
  • Встроенный PHP. enable_php в Dompdf выполняет <script type="text/php">. NextPDF по умолчанию не выполняет PHP внутри документа, потому что это поверхность для инъекций. Перенесите эту логику в свой код PHP до writeHtml().
  • Разрешение относительных ресурсов. Dompdf разрешает <img src> относительно базовой тройки path/protocol/хост. NextPDF разрешает относительно рабочего набора документа. Во время перехода передавайте абсолютные пути или предварительно разрешённые data URI, чтобы устранить эту переменную.

writeHtml() выполняет компоновку за один проход в потоковом режиме, как описано в записи об архитектурном решении ADR-001. После компоновки не сохраняется промежуточный объект дерева фреймов, поэтому пиковая память зависит от размера документа, а не от количества узлов DOM. Бюджет производительности для примера из этого руководства — wall_ms: 2000, peak_mb: 128. Для больших документов разбивайте HTML по границам addPage(), а не создавайте одну многомегабайтную строку.

  • Нет удалённого извлечения через контекст потока. NextPDF не реализует механизм удалённого извлечения setHttpContext() / enable_remote из Dompdf. Разрешайте и проверяйте удалённые ресурсы в своём приложении, затем передавайте байты или data URI. Это устраняет поверхность server-side request forgery (SSRF), которую несёт enable_remote.
  • Нет выполнения кода внутри документа. Отсутствие эквивалента enable_php — это намеренное усиление защиты, а не недоработка.
  • Метаданные документа, заданные через типизированные сеттеры, записываются в словарь сведений ISO 32000-2 §14 / Extensible Metadata Platform (XMP) (iso32000_2_sec14#x1.x5.p5). Не размещайте там секреты.
УтверждениеСтандартРазделreference_id (идентификатор ссылки)
Содержимое страницы — это отрисовка потока содержимого в модели opaque/transparent.ISO 32000-2§8
Размер бумаги сопоставляется с ограничивающим прямоугольником объекта страницы.ISO 32000-2§7
Шрифты HTML записываются как embedded/subset программы шрифтов.ISO 32000-2§9
Обработка пробельных символов / переносов строк зависит от движка.CSS Text 3§6.5

NextPDF создаёт содержимое ISO 32000-2. Он не заявляет, что перенесённый документ Dompdf будет визуально идентичным. Проверяйте вывод заново при каждой смене средства отрисовки.

Неприменимо. Core покрывает этот путь перехода с HTML на PDF.


Подробности перехода (обязательные разделы R6)

Заголовок раздела «Подробности перехода (обязательные разделы R6)»

Используйте его, если ваша команда применяет dompdf/dompdf для серверного преобразования HTML в PDF и переходит на движок NextPDF. Если вы вызываете только loadHtml / setPaper / render / output, то сопоставление методов покрывает всю вашу поверхность.

В область охвата входят методы фасада Dompdf, ключи Options, ожидания по паритету функций CSS, разрешение ресурсов и метаданные. Вне области охвата — внутренние объекты Dompdf FrameTree/Canvas/Stylesheet. NextPDF не имеет публичных аналогов, поэтому не переносите код, который обращается к ним; замените его публичным API.

Покрытие означает совместимость по поведению, а не готовую замену. NextPDF не имеет Dompdf-совместимой прослойки класса (в отличие от пути TCPDF; см. /migration/tcpdf-compat/). Перепишите каждое место вызова с помощью сопоставления методов. Матрица поддержки CSS, строки “Verified”, полностью определяет ожидания по функциям CSS. Это руководство не повторяет статус по каждому свойству.

Параметр Dompdf (ключ / сеттер)NextPDFПримечания
default_paper_size / setDefaultPaperSize() ; setPaper($size,...)Config->pageSize (PageSize VO)Именованные размеры становятся явными размерами в точках. new PageSize(595.276, 841.890, 'A4') — это значение по умолчанию для createStandalone().
default_paper_orientation / setDefaultPaperOrientation()поменяйте местами PageSize width/heightNextPDF не имеет флага ориентации. Альбомная страница — это PageSize с шириной > высоты.
dpi / setDpi()(не глобальный параметр)NextPDF работает в точках PDF (1/72 дюйма). Размер изображений задаётся для каждого изображения, а не множителем точек на дюйм (DPI) для документа. Пересчитайте фиксированные размеры в пикселях в точки.
enable_remote / setIsRemoteEnabled()(нет эквивалента — по замыслу)Разрешайте удалённые ресурсы в своём коде; см. Замечания по безопасности.
enable_html5_parser / setIsHtml5ParserEnabled()(всегда разбирает HTML)Отдельного переключателя нет: парсер является частью конвейера.
enable_php / setIsPhpEnabled()(нет эквивалента — по замыслу)PHP внутри документа не поддерживается. Вынесите логику из шаблона.
font_dir / setFontDir()Config->fontsDirectoryСтрока с каталогом шрифтов.
chroot(разрешайте в приложении)NextPDF не принимает параметр ограничения файловой системы. Проверяйте пути перед передачей байтов.
default_font / setDefaultFont()CSS font-family / зарегистрированный шрифтЗадавайте значение по умолчанию в базовой таблице стилей или при регистрации шрифта, а не глобальным параметром.
enable_font_subsetting / setIsFontSubsettingEnabled()(всегда создаёт подмножество)NextPDF всегда создаёт подмножества встроенных шрифтов (ISO 32000-2 §9, iso32000_2_sec9#x1.x45.p7). Режима “выключено” нет; режим Dompdf с выключенным флагом не имеет эквивалента и не нужен.
  • Движок компоновки. Dompdf и NextPDF используют независимые реализации компоновки CSS. Схлопывание пробельных символов и переносы строк специфицированы, но остаются зависимыми от движка (CSS Text 3 §6.5, css_text_3#x1.x6.x5.p20). Ожидайте различий в переносе строк и разбивке на страницы в плотном тексте. После перехода заново зафиксируйте визуальный эталон.
  • Граница отрисовки. Нет render()/output() двухфазной границы (см. Крайние случаи).
  • Разрешение ресурсов. Обработка базового пути/протокола/хоста отличается от рабочего набора документа.
  • Модель DPI. Точки PDF отличаются от множителя DPI в Dompdf.
  • Метаданные. Произвольные пары addInfo() отличаются от типизированных сеттеров (ISO 32000-2 §14, iso32000_2_sec14#x1.x5.p5).

Это документированные различия в поведении, а не дефекты какого-либо из движков.

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

Заголовок раздела «Не поддерживается / нет прямого эквивалента»
  • enable_php (PHP внутри документа) — намеренно отсутствует.
  • setHttpContext() / enable_remote — удалённое извлечение — намеренно отсутствует.
  • Публичный доступ к FrameTree / Canvas / Stylesheet — нет публичного аналога.
  • dpi как глобальный множитель документа — не моделируется.

Код, который зависит от них, нельзя перенести напрямую. Удалите его или перевыразите в коде приложения, как описано выше.

  1. Добавьте nextpdf/core рядом с dompdf/dompdf. Пока не удаляйте Dompdf.
  2. Выберите один документ с низким риском. Перепишите его место вызова с помощью сопоставления методов и удалите вызов render().
  3. Сгенерируйте оба PDF из одних и тех же входных данных и сравните их визуально. Считайте различия ожидаемыми, потому что движки независимы, и принимайте решение о приёмке для каждого документа.
  4. Преобразуйте использование параметров с помощью карты параметров; пересчитайте размеры, производные от DPI, в точки.
  5. Заранее разрешайте удалённые и относительные ресурсы в абсолютные пути или data URI, чтобы устранить переменную разрешения.
  6. Повторяйте для каждого документа, от наименьшего риска к наибольшему. Держите оба движка установленными, пока не будет переключено последнее место вызова.
  7. Удаляйте dompdf/dompdf из composer.json только после последнего переключения.
  • Сохраните снимок вывода Dompdf для репрезентативных документов до изменения кода. Используйте эталонные входные данные, а не эталонные байты, потому что байты будут различаться.
  • Для каждого перенесённого документа проверяйте вывод NextPDF собственной приёмочной проверкой, например визуальным сравнением или проверками извлечения текста. NextPDF покрывает поведение собственного конвейера HTML с помощью examples/08-html-basic.php и набора tests/ Html в Core. Приёмка перехода зависит от конкретного документа, и вы отвечаете за её подтверждение.
  • Добавьте регрессионный тест для каждого перенесённого документа, чтобы заметить изменения при будущих обновлениях движка.

Каждое утверждение NextPDF о поведении на этой странице подкреплено внутрирепозиторным тестом, примером, сигнатурой исходного кода или записью об архитектурном решении (ADR), а для свойств формата PDF — разделами ISO 32000-2 / CSS, закреплёнными через Retrieval-Augmented Generation (RAG) во фронтматтере citations: и таблице Соответствие. О поведении Dompdf говорится только в формулировке “независимый движок — ожидайте документированных различий”. Эта страница не заявляет о паритете, если это не подтверждено внутрирепозиторным артефактом.

NextPDF утверждение о поведенииВнутрирепозиторное доказательство (путь)
createStandalone() по умолчанию создаёт страницу A4 в книжной ориентации (595.276 × 841.890 pt).src/Core/Config.php (по умолчанию PageSize(595.276, 841.890, 'A4')); tests/Unit/Core/DocumentCreateStandaloneAndConfigWithersEdgeCaseTest.php (createStandaloneWithNullConfigBuildsDocumentWithA4Defaults).
writeHtml() выполняет компоновку за один проход в потоковом режиме; после компоновки DOM не сохраняется.docs/architecture/adr/ADR-001-stream-based-rendering-pipeline.md; src/Core/Concerns/HasTextOutput.php (writeHtml()).
writeHtml() автоматически создаёт первую страницу, если ни одной нет.tests/Unit/Core/Concerns/DocumentTextOutputFontSubsettingAndBorderEdgeCaseTest.php (writeHtmlAutoCreatesFirstPageWhenNoPagesExist).
output() / save() / getPdfData() — это методы вывода (без render/output в две фазы).src/Core/Concerns/HasOutput.php (output(), save(), getPdfData()); tests/Unit/Core/Concerns/DocumentOutputDestinationDispatchTest.php.
Назначение вывода — это перечисление NextPDF\Contracts\OutputDestination (Inline/Download/File/String).src/Contracts/OutputDestination.php; tests/Unit/Core/Concerns/DocumentOutputDestinationDispatchTest.php.
Шрифты HTML всегда записываются как embedded/subset программы.tests/Unit/Core/Concerns/DocumentTextOutputFontSubsettingAndBorderEdgeCaseTest.php (recordUsedCharactersAffectsFontSubsetting); ISO 32000-2 §9 (фронтматтер citations:).
Типизированные сеттеры метаданных (setTitle/setAuthor) заменяют произвольный addInfo().src/Core/Concerns/HasMetadata.php (setTitle(), setAuthor()); tests/Unit/Core/Concerns/DocumentInfoMetadataSetterBaselineTest.php.
Полный конвейер HTML (исполняемая основа этого руководства).examples/08-html-basic.php; набор tests/Unit/Html/ в Core.
Обработка пробельных символов / переносов строк зависит от движка (различие компоновки).CSS Text 3 §6.5 (фронтматтер citations: + Соответствие).

Поскольку оба пакета остаются установленными до окончательного переключения, откат для ещё не преобразованного места вызова означает возврат этого места вызова к пути Dompdf. После окончательного переключения откат означает восстановление dompdf/dompdf и прежнего места вызова из системы контроля версий. Миграция данных не требуется; меняется только код.

См. Производительность. Однопроходная модель означает, что переход не добавляет затрат на удержание дерева фреймов. Основное изменение затрат на документ — предварительное разрешение ресурсов из шага 5, которое можно кэшировать.

  • Оставление render() на месте, что вызывает фатальную ошибку неопределённого метода.
  • Передача байтов, отличных от UTF-8, после отказа от $encoding, что вызывает незаметное искажение символов.
  • Ожидание побайтово или попиксельно идентичного вывода от независимых движков. Это руководство никогда не заявляет о готовой замене или 100%-й совместимости.
  • Опора на шаблоны enable_php, которые необходимо переработать и убрать.
  • Восприятие матрицы поддержки CSS как рекомендательной. Это авторитетный источник по проверенным функциям, определяющий, чего ожидать.