跳到內容

從 mPDF 遷移到 NextPDF

本指南帶你把以 mPDF 為基礎的程式碼搬移到 NextPDF core。mPDF 的核心動詞是 WriteHTML(),可直接對映到 Document::writeHtml()。真正費工的是建構式 config 陣列的對映(mPDF 會把所有設定都放在傳給 new Mpdf([...]) 的單一關聯陣列中),以及字型處理差異。NextPDF 與 mPDF 是各自獨立的引擎,因此遷移後的文件與 mPDF 輸出 相容,但並非逐位元組相同。本指南涵蓋動詞對映、config 陣列對映、字型差異、CSS 支援差異、行為差異,以及安全遷移順序。

HTML/CSS 功能是否已驗證(Verified),以 CSS 支援對照表 為準。本指南描述的是行為,並未主張與 mPDF 視覺上等價。

Terminal window
composer require nextpdf/core:^3

過渡期間請保留 mpdf/mpdf 的安裝。等到最終切換之後再移除它(見 安全遷移順序 一節)。

mPDF 的 Mpdf 物件是一個龐大的單一 facade(外觀)。它由一個建構式陣列設定,再由 WriteHTML() 搭配分頁動詞(AddPageSetHTMLHeaderSetHTMLFooter)驅動。NextPDF 會把設定拆出來,放進不可變的 NextPDF\Core\Config 值物件,並以 Document::writeHtml() 驅動內容。它沒有建構式的「mode」字串。NextPDF 會剖析你傳入的 HTML,再以 save()output()getPdfData() 輸出文件。

字型:mPDF 隨附一個字型目錄,再搭配一份 fontdata 對映表與一組「核心字型」備援集。NextPDF 會透過單一字型目錄加上 CSS font-family 比對來 resolve(解析)字型,並 一律 對內嵌字型做子集化(ISO 32000-2 §9,iso32000_2_sec9#x1.x45.p7)。字型的 matching/fallback(比對/備援)是各引擎自訂的(CSS Fonts 4 §5.5,css_fonts_4#x1.x5.x5.x1.p13),因此字形替換結果可能不同。這是主要可見的差異,詳見 字型處理差異 一節。

NextPDF 的 HTML API 請參考 Html 模組。主要進入點包括:Document::createStandalone()Document::writeHtml(string $html): staticDocument::writeHtmlCell(...)Document::addPage()Document::output(?string, OutputDestination)Document::save(string $path): voidDocument::getPdfData(): string,以及 NextPDF\Core\Config 值物件。

下列 mPDF 公開方法名稱,已對照上游公開儲存庫(mpdf/mpdfdevelopment)逐一確認;請參見儲存庫內的 _source-sidecar-upstream-api.md 來源側錄檔。這裡未重製任何上游文件的文字內容。

mPDFNextPDF說明
new Mpdf([...])Document::createStandalone($config)mPDF 的 config 陣列會對映到 NextPDF\Core\Config;見 config 對映 一節。長壽命的 worker 請使用 DocumentFactory
$mpdf->WriteHTML($html)$doc->writeHtml($html)直接對映。mPDF 的第二個 $mode 引數(完整文件、僅 CSS 或單一元素)在 NextPDF 沒有對應項;請改傳完整的 HTML。
$mpdf->WriteFixedPosHTML(...)$doc->writeHtmlCell(...)具有定位/尺寸的 HTML 區域;對映 x/y/width/height 等引數。
$mpdf->AddPage(...)$doc->addPage()mPDF 那種逐次呼叫時傳入的 orientation/format/邊界覆寫,在 NextPDF 中不是引數;請改在呼叫之間調整文件模型。
$mpdf->SetHTMLHeader($html) / SetHTMLFooter($html)透過 Layout API 設定 header/footer(頁首/頁尾)mPDF 的執行階段 HTML 頁首會對映到 NextPDF 的 header/footer 機制,而不是本文頂端的內嵌 HTML。
$mpdf->Output($name, $dest)$doc->output($name, OutputDestination::…)mPDF 的目的地字元(I/D/F/S)會對映到 OutputDestination 列舉(Inline/Download;file 改用 save(),string 改用 getPdfData())。
$mpdf->Output('','S')$doc->getPdfData()回傳位元組。
$mpdf->Output($path,'F')$doc->save($path)寫入檔案路徑。
$mpdf->SetTitle($t)$doc->setTitle($t)會落在 ISO 32000-2 §14 的 info 字典/XMP(iso32000_2_sec14#x1.x5.p5)。
$mpdf->SetProtection($perms,...)$doc->setEncryption(...)(Security API,安全性 API)權限是讀取器配合性的,並非存取控制;見 安全性說明 一節。
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
// mPDF:
// $mpdf = new \Mpdf\Mpdf();
// $mpdf->WriteHTML('<h1>Invoice</h1>');
// $mpdf->Output('out.pdf', \Mpdf\Output\Destination::FILE);
// NextPDF — default page 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/04-text-and-fonts.php 一致;它是本指南中可實際執行、展示字型處理概念的範例。它使用明確的頁面尺寸、邊界,以及一段會觸發字型選取的正文內容。

<?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: new Mpdf(['format'=>'A4','margin_left'=>20, ...]).
// Margin constructor order is (top, right, bottom, left) — NOT L,R,T,B.
$config = new Config(
pageSize: new PageSize(595.276, 841.890, 'A4'),
margins: new Margin(16.0, 20.0, 16.0, 20.0), // top,right,bottom,left in points
fontsDirectory: __DIR__ . '/fonts',
);
$doc = Document::createStandalone($config);
$doc->setTitle('Quarterly Report');
$doc->addPage();
$html = <<<'HTML'
<h1 style="font-family:'DejaVu Sans';color:#1E3A8A;">Quarterly Report</h1>
<p>Body text resolves through CSS font-family matching against the configured
fonts directory. mPDF's fontdata map has no direct analogue — register the
family via CSS and the fonts directory instead.</p>
HTML;
$doc->writeHtml($html);
// Equivalent of $mpdf->Output('report.pdf', Destination::DOWNLOAD):
$doc->output('report.pdf', OutputDestination::Download);
  • $mode 引數位於 WriteHTML 上。 mPDF 的 WriteHTML($html, $mode)(2 = 僅 CSS,1 = 元素)並無對等項。請把你的 CSS 內嵌進傳入的 HTML;沒有「先寫 CSS 再寫本文」這種流程。
  • AddPage 的覆寫。 mPDF 允許 AddPage() 透過引數在文件中途變更 format/orientation。NextPDF 的 addPage() 不接受這類引數;尺寸變更要透過文件,而不是透過頁面呼叫。
  • 頁首/頁尾 HTML。 mPDF 的執行階段頁首是另外註冊的 HTML 片段;請勿把它們貼進本文裡。請把它們對映到 NextPDF 的 header/footer 機制。
  • 字型名稱。 mPDF 透過它的 fontdata/core-font 表來正規化字型名稱。NextPDF 會把 CSS 的 font-family 對字型目錄做比對;某個在 mPDF 中可默默解析的別名,可能需要明確的 @font-face/family 宣告。
  • 目的地字元。 NextPDF 不接受 'I'/'D'/'F'/'S';請使用 OutputDestination 列舉,或改用 save()/getPdfData()

writeHtml() 是單次處理(ADR-001);尖峰記憶體會隨文件大小變動,而不是隨保留的 DOM 變動。本指南範例的預算:wall_ms: 2000, peak_mb: 128。對於長文件,請把內容分頁到多個 addPage(),而不要塞進一個巨大的字串。這與 mPDF 的 $mode 分段做法屬於同一類建議,只是改用頁面模型來表達。

  • 權限是讀取器配合性的。 SetProtection()setEncryption() 提供的是機密性,而非存取控制:ISO 權限位元是否生效,取決於讀取器是否配合。請勿把加密向使用者描述成存取控制。
  • 中繼資料。 SetTitle() 與文件 info 會落在 ISO 32000-2 §14 的資訊字典/XMP(iso32000_2_sec14#x1.x5.p5);切勿在那裡存放任何祕密。
  • NextPDF 不會執行文件內的指令碼;也沒有任何 mPDF 指令可啟用該功能。
陳述規範條款參考 ID
字型會寫成 embedded/subset(內嵌/子集化)字型程式。ISO 32000-2§9
頁面的 format/margins(格式/邊界)會對映到頁面邊界框。ISO 32000-2§7
標題/保護中繼資料會落在 info 字典/XMP 中。ISO 32000-2§14
字型比對/備援是各引擎自訂的。CSS Fonts 4(CSS 字型規範)§5.5

NextPDF 產生的是 ISO 32000-2 內容;它並未主張與 mPDF 視覺上完全一致。renderer(渲染器)一旦變更,就需要重新審查輸出。

不適用。core 已涵蓋這裡描述的 mPDF 遷移路徑。


本指南適合在伺服器端使用 mpdf/mpdf 做 HTML 轉 PDF 的團隊。如果你的介面是 new Mpdf([...]) + WriteHTML + Output(外加選用的 header/footer),那麼 動詞對映config 對映 就已涵蓋。

範圍內:Mpdf 建構式 config 陣列、WriteHTML/Output/AddPage、headers/footers、字型、保護、中繼資料。範圍外:mPDF 的內部類別,以及 QR/條碼/浮水印的輔助介面(請把那些對映到對應的 NextPDF 模組 — Barcode、Graphics — 本文不涵蓋)。

這是行為相容,並非可直接替換的 shim(相容層):沒有 Mpdf 類別的相容層。每一處呼叫點都需要改寫。CSS 功能的預期,以 CSS 支援對照表 的 Verified 列為準。

mPDF 的 config 鍵已對照上游公開儲存庫(mpdf/mpdfdevelopment)確認。這裡未重製任何上游文件的文字內容。

mPDF config 鍵NextPDF說明
mode(無對等項)mPDF 的 mode 字串('utf-8''c''+aCJK' 等)會選擇 font/script(字型/文字系統)行為。NextPDF 一律是 Unicode;CJK 由字型選取處理,而非由某個 mode 處理。請刪掉這個鍵。
formatConfig->pageSizePageSize VO)具名格式會轉成明確的點(point)尺寸;陣列 [w,h] 對映到一個 PageSize
orientation對調 PageSize 的 width/height沒有方向旗標;橫向 = 寬 > 高。
default_font_sizeCSS 基準 font-size透過你的基準樣式表設定,而不是透過建構式的鍵。
default_fontCSS font-family /已註冊字型透過 CSS/字型註冊來設定預設字族。
margin_left / margin_right / margin_top / margin_bottomConfig->marginsMargin VO),以點為單位單一 Margin 值物件;它的建構式順序是 Margin(top, right, bottom, left)(請對照 src/ValueObjects/Margin.php 確認),而不是 mPDF 的鍵順序。
margin_header / margin_footer透過 Layout API 設定 header/footer 偏移請對映到 NextPDF 的 header/footer 設定,而不是建構式的鍵。
  • 單一字型目錄。 mPDF 的字型目錄清單 + fontdata 對映表 + 核心字型備援,全部收斂為 Config->fontsDirectory 加上 CSS font-family 比對。
  • 一律子集化。 NextPDF 一律對內嵌字型做子集化(ISO 32000-2 §9,iso32000_2_sec9#x1.x45.p7);mPDF 的子集化旗標並無對等項,也不需要。
  • 比對是各引擎自訂的。 字型的 matching/fallback 因引擎而異(CSS Fonts 4 §5.5,css_fonts_4#x1.x5.x5.x1.p13);某個 mPDF 字型別名可能需要明確的 @font-face 或精確的字族名稱。遷移後請重新建立字形繪製的基準;替換差異是預期內,並非缺陷。
  • 字型替換(見上文)— 主要可見的差異。
  • WriteHTML 上沒有 $mode — 請傳入含內嵌 CSS 的完整 HTML。
  • 沒有逐 AddPage 的 format 覆寫 — 尺寸變更要透過文件。
  • 權限是讀取器配合性的(見 安全性說明 一節)。
  • 獨立的版面引擎 — 在密集內容上,斷行/分頁會有所不同;請重新建立視覺差異的基準。

這些都是有記錄的行為差異,而非任一引擎的缺陷。

  • mode 建構式字串 — 未建模(一律是 Unicode)。
  • AddPage() 的 format/orientation/邊界引數 — 在 NextPDF 中不是引數。
  • mPDF 的 fontdata 對映表 — 由字型目錄加 CSS 比對取代。
  • mPDF 的 'I'/'D'/'F'/'S' 目的地字元 — 改由 OutputDestination 列舉加上 save()/getPdfData() 取代。
  1. nextpdf/corempdf/mpdf 並存安裝(暫時保留 mPDF)。
  2. 選一份低風險的文件。把 new Mpdf([...]) 依照 config 對映 轉換,並把 WriteHTML/Output 依照 動詞對映 轉換。
  3. 把該文件用到的字型註冊到 Config->fontsDirectory,並為任何 mPDF 別名加上明確的 @font-face/family 宣告。
  4. 對同一份輸入產生兩份 PDF;做視覺差異比對。差異(字型替換、斷行)對獨立引擎而言是預期的 — 請以文件為單位確認並接受。
  5. 把任何 header/footer HTML 對映到 NextPDF 的 header/footer 機制。
  6. 逐份文件重複,從最低風險開始;保留 mPDF 安裝直到最後一次切換。
  7. 在最終切換之後,把 mpdf/mpdfcomposer.json 移除。
  • 在改動程式碼之前,先快照代表性文件的 mPDF 輸出(作為 golden 基準;位元組會有所不同)。
  • 逐份遷移的文件,都要透過你自己的驗收檢查來斷言(視覺差異比對 + 文字擷取)。NextPDF 的字型/HTML 行為由 examples/04-text-and-fonts.phpexamples/08-html-basic.php 加上核心 tests/ 的 Html/Font 測試套件實際驗證。遷移驗收因文件而異,由你自行負責。
  • 為每一份遷移的文件加上一個回歸測試。

本頁每一項 NextPDF 行為陳述,都有儲存庫內的測試、範例、原始碼簽章或 ADR 支持 — 若屬 PDF 格式特性,則由 front-matter(前置資料)citations: 中以 RAG 釘選的 ISO 32000-2 / CSS 條款,以及 符合性 表佐證。mPDF 的行為僅以「獨立引擎 — 預期會有記錄在案的差異」來陳述;不會主張任何儲存庫內成品無法證明的對等性。

NextPDF 行為主張儲存庫內佐證(路徑)
WriteHTML() 直接對映到 Document::writeHtml(string $html): staticsrc/Core/Concerns/HasTextOutput.phpwriteHtml());examples/08-html-basic.php
WriteFixedPosHTML(...) 對映到 writeHtmlCell(...)src/Core/Concerns/HasTextOutput.phpwriteHtmlCell())。
createStandalone() 的預設頁面是 A4 直向(595.276 × 841.890 pt)。src/Core/Config.php(預設 PageSize);tests/Unit/Core/DocumentCreateStandaloneAndConfigWithersEdgeCaseTest.php
Margin 的建構式順序是 (top, right, bottom, left)src/ValueObjects/Margin.php(提升屬性的順序)。
輸出目的地是 NextPDF\Contracts\OutputDestination 列舉;不接受 'I'/'D'/'F'/'S'src/Contracts/OutputDestination.php(列舉項 Inline/Download/File/String);tests/Unit/Core/Concerns/DocumentOutputDestinationDispatchTest.php
Output('','S')getPdfData()Output($path,'F')save($path)src/Core/Concerns/HasOutput.phpgetPdfData()save()output())。
SetProtection() 對映到 setEncryption(...);權限是讀取器配合性的。src/Core/Concerns/HasSecurity.phpsetEncryption());ISO 32000-2 §14(前置資料 citations:)。
SetTitle()setTitle();中繼資料會落在 info 字典/XMP 中。src/Core/Concerns/HasMetadata.phpsetTitle());tests/Unit/Core/Concerns/DocumentInfoMetadataSetterBaselineTest.php;ISO 32000-2 §14(前置資料 citations:)。
字型一律以子集化字型程式的形式內嵌。tests/Unit/Core/Concerns/DocumentTextOutputFontSubsettingAndBorderEdgeCaseTest.phpexamples/04-text-and-fonts.php;ISO 32000-2 §9(前置資料 citations:)。
字型比對/備援是各引擎自訂的(替換差異)。CSS Fonts 4 §5.5(front-matter citations: + 符合性 一節)。
writeHtml() 是單次處理;尖峰記憶體隨文件大小變動。docs/architecture/adr/ADR-001-stream-based-rendering-pipeline.md

兩個套件都會保留安裝直到最終切換,因此逐一呼叫點的回滾,就是把該呼叫點還原回 mPDF 路徑。最終切換之後,回滾就是從版本控制還原 mpdf/mpdf 與先前的程式碼。不涉及任何資料遷移。

效能 一節。單次處理模型移除了 mPDF 那種保留緩衝區的成本。新增的逐文件成本來自急切(eager)的字型解析(步驟 3),可透過字型目錄快取。

  • 保留 mode 鍵並期望它帶來 CJK 行為(該鍵會被刪掉;CJK 是字型選取)。
  • 傳入 WriteHTML($html, 2)(僅 CSS 模式)— 請改用內嵌 CSS。
  • 把 header/footer HTML 貼進本文裡。
  • 在沒有明確字族的情況下,期望某個 mPDF 別名得到相同字型。
  • 期望輸出 byte/pixel-identical(逐位元組/逐像素相同)(獨立引擎 — 本指南從未主張可直接替換或 100% 相容)。
  • 把 CSS 支援對照表當成僅供參考 — 它是已驗證功能的權威依據。