從 mPDF 遷移到 NextPDF
快速概覽
標題為「快速概覽」的區段本指南帶你把以 mPDF 為基礎的程式碼搬移到 NextPDF core。mPDF 的核心動詞是 WriteHTML(),可直接對映到 Document::writeHtml()。真正費工的是建構式 config 陣列的對映(mPDF 會把所有設定都放在傳給 new Mpdf([...]) 的單一關聯陣列中),以及字型處理差異。NextPDF 與 mPDF 是各自獨立的引擎,因此遷移後的文件與 mPDF 輸出 相容,但並非逐位元組相同。本指南涵蓋動詞對映、config 陣列對映、字型差異、CSS 支援差異、行為差異,以及安全遷移順序。
HTML/CSS 功能是否已驗證(Verified),以 CSS 支援對照表 為準。本指南描述的是行為,並未主張與 mPDF 視覺上等價。
composer require nextpdf/core:^3過渡期間請保留 mpdf/mpdf 的安裝。等到最終切換之後再移除它(見 安全遷移順序 一節)。
概念總覽
標題為「概念總覽」的區段mPDF 的 Mpdf 物件是一個龐大的單一 facade(外觀)。它由一個建構式陣列設定,再由 WriteHTML() 搭配分頁動詞(AddPage、SetHTMLHeader、SetHTMLFooter)驅動。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),因此字形替換結果可能不同。這是主要可見的差異,詳見 字型處理差異 一節。
API 介面
標題為「API 介面」的區段NextPDF 的 HTML API 請參考 Html 模組。主要進入點包括:Document::createStandalone()、Document::writeHtml(string $html): static、Document::writeHtmlCell(...)、Document::addPage()、Document::output(?string, OutputDestination)、Document::save(string $path): void、Document::getPdfData(): string,以及 NextPDF\Core\Config 值物件。
API 動詞對映
標題為「API 動詞對映」的區段下列 mPDF 公開方法名稱,已對照上游公開儲存庫(mpdf/mpdf 的 development)逐一確認;請參見儲存庫內的 _source-sidecar-upstream-api.md 來源側錄檔。這裡未重製任何上游文件的文字內容。
| mPDF | NextPDF | 說明 |
|---|---|---|
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 configuredfonts directory. mPDF's fontdata map has no direct analogue — register thefamily 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 遷移路徑。
另請參閱
標題為「另請參閱」的區段遷移細節(R6 必備章節)
標題為「遷移細節(R6 必備章節)」的區段這份指南適合誰
標題為「這份指南適合誰」的區段本指南適合在伺服器端使用 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 列為準。
建構式 config 陣列對映
標題為「建構式 config 陣列對映」的區段mPDF 的 config 鍵已對照上游公開儲存庫(mpdf/mpdf 的 development)確認。這裡未重製任何上游文件的文字內容。
| mPDF config 鍵 | NextPDF | 說明 |
|---|---|---|
mode | (無對等項) | mPDF 的 mode 字串('utf-8'、'c'、'+aCJK' 等)會選擇 font/script(字型/文字系統)行為。NextPDF 一律是 Unicode;CJK 由字型選取處理,而非由某個 mode 處理。請刪掉這個鍵。 |
format | Config->pageSize(PageSize VO) | 具名格式會轉成明確的點(point)尺寸;陣列 [w,h] 對映到一個 PageSize。 |
orientation | 對調 PageSize 的 width/height | 沒有方向旗標;橫向 = 寬 > 高。 |
default_font_size | CSS 基準 font-size | 透過你的基準樣式表設定,而不是透過建構式的鍵。 |
default_font | CSS font-family /已註冊字型 | 透過 CSS/字型註冊來設定預設字族。 |
margin_left / margin_right / margin_top / margin_bottom | Config->margins(Margin 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加上 CSSfont-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()取代。
安全遷移順序
標題為「安全遷移順序」的區段- 把
nextpdf/core與mpdf/mpdf並存安裝(暫時保留 mPDF)。 - 選一份低風險的文件。把
new Mpdf([...])依照 config 對映 轉換,並把WriteHTML/Output依照 動詞對映 轉換。 - 把該文件用到的字型註冊到
Config->fontsDirectory,並為任何 mPDF 別名加上明確的@font-face/family 宣告。 - 對同一份輸入產生兩份 PDF;做視覺差異比對。差異(字型替換、斷行)對獨立引擎而言是預期的 — 請以文件為單位確認並接受。
- 把任何 header/footer HTML 對映到 NextPDF 的 header/footer 機制。
- 逐份文件重複,從最低風險開始;保留 mPDF 安裝直到最後一次切換。
- 在最終切換之後,把
mpdf/mpdf從composer.json移除。
測試遷移
標題為「測試遷移」的區段- 在改動程式碼之前,先快照代表性文件的 mPDF 輸出(作為 golden 基準;位元組會有所不同)。
- 逐份遷移的文件,都要透過你自己的驗收檢查來斷言(視覺差異比對 + 文字擷取)。NextPDF 的字型/HTML 行為由
examples/04-text-and-fonts.php與examples/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): static。 | src/Core/Concerns/HasTextOutput.php(writeHtml());examples/08-html-basic.php。 |
WriteFixedPosHTML(...) 對映到 writeHtmlCell(...)。 | src/Core/Concerns/HasTextOutput.php(writeHtmlCell())。 |
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.php(getPdfData()、save()、output())。 |
SetProtection() 對映到 setEncryption(...);權限是讀取器配合性的。 | src/Core/Concerns/HasSecurity.php(setEncryption());ISO 32000-2 §14(前置資料 citations:)。 |
SetTitle() → setTitle();中繼資料會落在 info 字典/XMP 中。 | src/Core/Concerns/HasMetadata.php(setTitle());tests/Unit/Core/Concerns/DocumentInfoMetadataSetterBaselineTest.php;ISO 32000-2 §14(前置資料 citations:)。 |
| 字型一律以子集化字型程式的形式內嵌。 | tests/Unit/Core/Concerns/DocumentTextOutputFontSubsettingAndBorderEdgeCaseTest.php;examples/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 支援對照表當成僅供參考 — 它是已驗證功能的權威依據。