Dompdf から NextPDF への移行
このガイドでは、Dompdf ベースのコードベースを NextPDF の Html パイプラインへ移行する方法を説明します。Dompdf と NextPDF は、HTML を読み込み、レンダリングし、PDF を出力するという同じ流れを共有しているため、ほとんどの呼び出し箇所は機械的に置き換えられます。実際の移行作業の中心は、オプション対応表と CSS サポート差分の確認です。NextPDF と Dompdf は独立したエンジンであるため、Dompdf が生成したレイアウトは NextPDF の結果と互換性がありますが、バイト単位で同一になるわけではありません。このガイドでは、動詞の対応付け、オプションキーの対応付け、挙動の違い、安全な移行手順を扱います。
NextPDF が HTML/CSS 機能をサポートしていても、特定の Dompdf ドキュメントがピクセル単位で同一に再現される保証はありません。どの機能が Verified であるかは、CSS サポートマトリクス が正式な根拠です。このガイドは挙動を説明するものであり、視覚的な同等性を主張するものではありません。
インストール
「インストール」という見出しのセクションcomposer require nextpdf/core:^3移行期間中は dompdf/dompdf をインストールしたままにし(安全な移行手順 では、各呼び出し箇所が切り替わるまで両者を並行して実行します)、切り替えが完了したら削除します。
概念の概要
「概念の概要」という見出しのセクションDompdf の Dompdf オブジェクトは、DOM、スタイルシート、フレームツリー、キャンバスを保持する単一のファサードです。NextPDF では、これらの関心事を分離します。NextPDF\Core\Document がページモデルと出力を担い、HTML パイプラインは writeHtml() という 1 つのメソッドで駆動します。「レンダリングしてから出力する」という独立した 2 段階の手順はありません。writeHtml() はコンテンツを書き込みながらレイアウトを行い、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 サーフェス
「API サーフェス」という見出しのセクションNextPDF の Html API は 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 動詞の対応付け
「API 動詞の対応付け」という見出しのセクション以下の Dompdf 公開 API 名は、上流の公開リポジトリ(dompdf/dompdf、master)に対して確認済みです。リポジトリ内の _source-sidecar-upstream-api.md 来歴サイドカーを参照してください。上流のドキュメントテキストは一切複製していません。
| Dompdf | NextPDF | 注記 |
|---|---|---|
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 にはファイル読み込み用のバリアントはありません。I/O ポリシーをコード内に保つため、ファイルは呼び出し側で読み込んでください。 |
$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() | (リソースの resolve(解決)が異なります) | NextPDF は相対リソースを、ベースの path/protocol/host 三つ組ではなく、ドキュメントのワーキングセットに対して解決します。挙動の違い を参照してください。 |
$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(このガイドの実行可能な裏付け)を反映したサンプルで、明示的な非デフォルトの用紙サイズとマージンを使用しています。Dompdf の setPaper() に 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 thatis <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);エッジケースと注意点
「エッジケースと注意点」という見出しのセクション- 2 段階レンダリングはありません。
render()とoutput()の間で状態を検査する Dompdf コード(たとえばページ数の読み取り)には、その同じタイミングに相当する NextPDF の対応物はありません。代わりにwriteHtml()の後にドキュメントを照会してください。 - エンコーディング。 NextPDF は Dompdf の
$encodingパラメータを廃止しています。writeHtml()の前に入力を UTF-8 へ変換してください。Latin-1 のバイト列を渡すと、エラーではなく文字化けが発生します。 render()が残ったまま。 残っている$dompdf->render()形式の呼び出しには NextPDF のメソッドが存在せず、致命的な「undefined method」になります。切り替え時には削除し、スタブ化しないでください。- インライン PHP。 Dompdf の
enable_phpは<script type="text/php">を評価します。NextPDF には設計上、ドキュメント内の PHP 実行はありません(これはインジェクションの攻撃面になるためです)。そのロジックはwriteHtml()の前に、アプリケーション側の PHP コードへ移してください。 - 相対リソースの解決。 Dompdf は
<img src>をベースの path/protocol/host の三つ組に対して解決します。NextPDF はドキュメントのワーキングセットに対して解決します。移行中は、変動要因を排除するために絶対パスまたは事前解決済みのデータ URI を渡してください。
パフォーマンス
「パフォーマンス」という見出しのセクションwriteHtml() は単一のストリーミングパスでレイアウトを行います(ADR-001)。レイアウト後に保持される中間的なフレームツリーオブジェクトはないため、ピークメモリは DOM ノード数ではなくドキュメントサイズに連動します。このガイドの例のパフォーマンス予算は wall_ms: 2000, peak_mb: 128 です。大きなドキュメントでは、数メガバイトの文字列を 1 つ構築するのではなく、HTML を addPage() の境界をまたいで分割してください。
セキュリティに関する注記
「セキュリティに関する注記」という見出しのセクション- ストリームコンテキストによるリモート取得はありません。 NextPDF は Dompdf の
setHttpContext()/enable_remoteによるリモート取得経路を実装していません。リモートアセットはアプリケーション内で解決・検証してから、バイト列またはデータ URI を渡してください。これにより、enable_remoteに伴う SSRF の攻撃面を取り除けます。 - ドキュメント内のコード実行はありません。
enable_php相当のものが存在しないのは、欠陥ではなく意図的な堅牢化です。 - 型付きセッターで設定したドキュメントメタデータは、ISO 32000-2 §14 の情報ディクショナリ / XMP に書き込まれます(
iso32000_2_sec14#x1.x5.p5)。そこに秘密情報を置かないでください。
| 記述 | 仕様 | 条項 | リファレンス 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 ドキュメントが視覚的に同一であることは主張しません。レンダラーを変更する場合は、必ず出力を再レビューする必要があります。
商用に関する補足
「商用に関する補足」という見出しのセクション該当しません。コアは、ここで説明する HTML-to-PDF の移行経路をカバーします。
移行の詳細(R6 必須セクション)
「移行の詳細(R6 必須セクション)」という見出しのセクションサーバーサイドの HTML-to-PDF に dompdf/dompdf を使用していて、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/height | NextPDF には向きのフラグはありません。横向きのページは width > height の 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 はファイルシステムの jail オプションを受け取りません。バイト列を渡す前にパスの検証を実施してください。 |
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()の 2 段階の境界はありません(エッジケース を参照)。 - リソース解決。 ベースパス / プロトコル / ホストと、ドキュメントのワーキングセット。
- DPI モデル。 ポイントと Dompdf の DPI 倍率。
- メタデータ。 自由形式の
addInfo()ペアと型付きセッター(ISO 32000-2 §14、iso32000_2_sec14#x1.x5.p5)。
これらは文書化された挙動の違いであり、いずれのエンジンの欠陥でもありません。
サポート対象外 / 直接の同等物なし
「サポート対象外 / 直接の同等物なし」という見出しのセクションenable_php(ドキュメント内 PHP)— 意図的に存在しません。setHttpContext()/enable_remoteリモート取得 — 意図的に存在しません。- 次のオブジェクトへの公開アクセス:
FrameTree/Canvas/Stylesheet— 公開された対応物はありません。 dpi— ドキュメント全体の倍率としてはモデル化されていません。
これらに依存するコードは「移行」できません。上記の行に従い、該当部分を削除するか、アプリケーションコード内で再表現します。
安全な移行手順
「安全な移行手順」という見出しのセクションdompdf/dompdfと並べてnextpdf/coreを追加します。Dompdf はまだ削除しません。- リスクの低いドキュメントを 1 つ選びます。動詞の対応付け を使用してその呼び出し箇所を書き換え、
render()呼び出しを削除します。 - 同じ入力に対して両方の PDF を生成し、視覚的に差分を取ります。差異は想定されるもの(独立したエンジン)として扱い、ドキュメントごとに受け入れ可否を判断します。
- オプションの使用箇所は オプション対応表 を使用して変換し、DPI に由来するサイズをポイントに再計算します。
- 解決の変動要因を排除するため、remote/relative のアセットを絶対パスまたはデータ URI に事前解決します。
- リスクの低いものから高いものへ、ドキュメントごとに繰り返します。最後の呼び出し箇所が切り替わるまで、両方のエンジンをインストールしたままにします。
- 最後の切り替えが完了した後にのみ、
dompdf/dompdfをcomposer.jsonから削除します。
移行のテスト
「移行のテスト」という見出しのセクション- コードを変更する前に、代表的なドキュメントの Dompdf 出力をスナップショットします(ゴールデンのバイト列ではなくゴールデンの入力です — バイト列は異なります)。
- 移行した各ドキュメントについて、NextPDF の出力をチームの受け入れチェック(視覚的な差分、テキスト抽出のアサーション)に通します。NextPDF 自身の HTML パイプラインの挙動は
examples/08-html-basic.phpとコアのtests/Html スイートでカバーされています。移行の受け入れはドキュメント固有であり、それをアサートする責任は利用側にあります。 - 将来のエンジン更新を検知できるよう、移行した各ドキュメントに回帰テストを追加します。
エビデンス / トレーサビリティ
「エビデンス / トレーサビリティ」という見出しのセクションこのページにあるすべての NextPDF の挙動に関する記述は、リポジトリ内のテスト、例、ソースのシグネチャ、または ADR によって裏付けられています。PDF フォーマットのプロパティである場合は、フロントマターの citations: および 適合性 表にある RAG 固定の ISO 32000-2 / CSS 条項によって裏付けられています。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 の 2 段階はありません)。 | 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/ スイート。 |
| ホワイトスペース / 行分割はエンジン固有です(レイアウトの差分)。 | CSS Text 3 §6.5(フロントマターの citations: + 適合性)。 |
ロールバック
「ロールバック」という見出しのセクション最終的な切り替えまで両方のパッケージがインストールされたままであるため、未変換の呼び出し箇所のロールバックとは、その 1 つの呼び出し箇所を Dompdf の経路に戻すことを意味します。最終的な切り替えの後では、ロールバックとは dompdf/dompdf と以前の呼び出し箇所をバージョン管理から復元することを意味します。データ移行は伴いません — コードのみです。
パフォーマンスに関する考慮事項
「パフォーマンスに関する考慮事項」という見出しのセクション詳しくは パフォーマンス を参照してください。単一パスのモデルであるため、移行によってフレームツリーの保持コストが新たに発生することはありません。ドキュメントごとの主なコスト変化は、アセットを事前に再解決すること(手順 5)であり、これはキャッシュできます。
よくある落とし穴
「よくある落とし穴」という見出しのセクション- 次を残したままにする:
render()(致命的な undefined method)。 - 廃止された
$encodingの後に UTF-8 でないバイト列を渡す(無言の文字化け)。 - バイト単位またはピクセル単位で同一の出力を期待する(独立したエンジン — このガイドはドロップインや 100% の互換性を一切主張しません)。
- 依存先の
enable_phpテンプレート(リファクタリングで取り除く必要があります)。 - CSS サポートマトリクスを参考程度に扱う — これは何を期待すべきかを示す Verified 機能の正式な根拠です。