一套引擎,通吃各種框架
Spec: PSR-11 Container, §1.1.2PSR-11 Container §1.1.2Spec: PSR-4 Autoloader, §3PSR-4 Autoloader §3
快速概覽
標題為「快速概覽」的區段大多數成長中的 PHP 環境,最後都會用上不止一種框架。NextPDF 是一套 PDF 引擎,能以各框架自己的方式去迎合每一種:為 Laravel、Symfony 與 CodeIgniter 提供慣用的橋接,另有一條獨立執行路徑,給那些不在任何框架中執行的程式碼使用。文件模型是共用的。改變的只有你呼叫它的方式。
為什麼這很重要
標題為「為什麼這很重要」的區段為每個技術堆疊各備一套不同的 PDF 函式庫,是一筆無聲的稅。每一套都有自己的怪癖、自己的字型處理方式,以及對「何謂有效」自成一格的看法。一張從 Laravel 服務算繪正確的發票,從 Symfony worker 算繪出來時可能有著細微的差異,因為畫它的是另一套函式庫。如此一來,你的封存目標、你的簽章位置,以及你的可及性標記,全都取決於是哪個團隊交付了那份文件。錯誤回報寫著「這份 PDF 不對」,而答案取決於是三套引擎中的哪一套產生了它。
統一採用一套引擎,便能讓這片表面坍縮收攏。只有一個地方決定 PDF/A 設定檔、只有一條字型管線要認證、只有一個驗證器要信任。你恰好身處哪個框架,不再是文件是否正確的一個變數。
精簡版說明
標題為「精簡版說明」的區段- 核心引擎與框架無關。
nextpdf/core對 HTTP、路由或容器接線一無所知。它就是一套 PDF 2.0 引擎,僅此而已。 - 每個橋接只負責調整,而非重新實作。 Laravel、Symfony 與 CodeIgniter 套件給你一個 facade 或 factory、一個 HTTP 回應輔助工具,以及一條佇列化或非同步的產生路徑——全都建立在同一套引擎之上。
- 橋接跟隨你的框架,而不是你的文件。 它改變的是你如何呼叫引擎,絕不改變引擎能產生什麼。
- 獨立路徑始終可用。 一個 CLI 工具、一個常駐程式,或一個函式庫,沒有框架可橋接;它直接建構一份文件。
- 同一個文件模型橫跨全部四者。 同樣的值物件、列舉與輸出契約處處出現,因此一份文件可在不同呼叫端之間原封不動地移動。
NextPDF 的處理方式
標題為「NextPDF 的處理方式」的區段這套架構是一道刻意的切分。引擎才是資產;橋接是一個薄薄的轉接層,講某一個框架的慣用語。一個橋接會透過標準的自動載入(Spec: PSR-4 Autoloader, §3PSR-4 Autoloader §3)在共用核心之上註冊一個小型命名空間,並透過容器契約(Spec: PSR-11 Container, §1.1.2PSR-11 Container §1.1.2)把一份文件交回給你。那份契約正是這裡默默的功臣:它允許同一識別符的兩次解析回傳不同的實例,而這正是橋接如何在每個請求給你一份全新、可丟棄的文件,同時又把已解析的字型註冊表與影像快取維持為行程層級的單例。長壽命的 worker——Octane、RoadRunner、Swoole、Messenger——便能在結構上享有攤提後的字型解析,且不會有跨請求的狀態洩漏。
這四種慣用語只在表面有所不同:
- Core enginenextpdf/core — the framework-agnostic PDF 2.0 engine; the single shared document model, value objects, and output contract.
- Laravel bridgenextpdf/laravel — auto-discovered provider, a Pdf facade, a PdfResponse helper, and a queued GeneratePdfJob.
- Symfony bridgenextpdf/symfony — an auto-registered bundle, an injectable PdfFactory, a PdfResponse, and an optional Messenger handler.
- CodeIgniter bridgenextpdf/codeigniter — a service and pdf() helper, a Pdf library over a disposable Document, and a PdfResponse.
- StandaloneNo framework to bridge from — construct a Document directly in a CLI tool, daemon, or library.
由左至右讀這張圖,學到的就是那份對稱。每一種表面都解析到同一個 Document。Laravel facade、Symfony factory、CodeIgniter service 與獨立建構式,是通往同一個房間的四道門。
實務範例
標題為「實務範例」的區段同樣的三行意圖,以每一種慣用語表達。建構文件的主體——頁面、字型、儲存格、簽署、符合性——在四者中完全相同,因為那是同一套引擎。
<?php
declare(strict_types=1);
// Laravel — resolve a fresh document from the container.use NextPDF\Contracts\PdfDocumentInterface;$document = app(PdfDocumentInterface::class);
// Symfony — inject the factory, then ask it for a document.use NextPDF\Symfony\Service\PdfFactory;$document = $factory->create(); // PdfFactory injected into your service
// CodeIgniter — pull it from the Services layer.use NextPDF\CodeIgniter\Config\Services;$document = Services::pdfDocument();
// Standalone — no framework; construct it directly.use NextPDF\Core\Document;$document = Document::createStandalone();
// From here, the code is identical regardless of how $document arrived.$document->addPage();$document->cell(0, 10, 'One engine, every framework', newLine: true);$bytes = $document->getPdfData();最前面那幾行是唯一的差異。之後的一切都可移植:把一個建構文件的服務從 Symfony 搬到一個獨立 worker,算繪程式碼也不會改變,因為它所依賴的契約並未改變。
常見誤解
標題為「常見誤解」的區段常見的假設是,框架橋接會解鎖能力——以為長期簽章驗證或結構化電子發票之所以到位,是因為你安裝了 nextpdf/laravel,而不是直接呼叫引擎。並非如此。橋接改變的是呼叫端,絕不改變引擎的觸及範圍。諸如 PDF/A 輸出與 PAdES 基準簽署等核心能力是開源的,並觸及每一種表面;進階能力由某個版本解鎖,隨後便可透過任何橋接或獨立路徑同等使用。選擇一項框架整合,並不是在選擇一組功能集。
與之相對的誤解是,「一套引擎」必定意味著對每份文件只有一條算繪路徑。並非如此。行程內引擎直接算繪 PDF;當一份文件確實需要瀏覽器等級的版面引擎時,會交由一個轉譯器套件處理。算繪與呼叫是兩個分開的軸——整合決策指南正是把它們對應起來的地方。
限制與邊界
標題為「限制與邊界」的區段橋接不會擴張引擎能算繪的內容。那是個誠實的限制,而它正是重點:能力存在於核心與層級,而不在於你用來取用它的轉接層。
| Edition | Availability |
|---|---|
| Core | 每個橋接(Laravel、Symfony、CodeIgniter)與獨立路徑都採用 Apache-2.0 授權,並針對 Core 運作。它們調整或公開引擎;它們不閘控功能,也不改變它能產生什麼。 |
| Pro | 諸如長期簽章驗證(PAdES B-LT 與 B-LTA)等進階能力由某個版本解鎖,隨後便透過任何橋接或獨立路徑以相同方式取用——絕不是靠切換框架。PDF/A 封存輸出與 PAdES 基準簽署(B-B 與 B-T)已內建於 Core,透過每一種表面都以相同方式提供。 |
| Enterprise | 結構化電子發票(EN 16931)與更深入的符合性工具同樣屬於版本能力,無論由哪一種表面呼叫引擎,亦皆相同,而符合性驗證本身則隨 Core 一同提供。 |
另有兩道邊界值得明白說清楚。第一,每個橋接都追隨其框架的某個目前主要版本——Laravel、Symfony 與 CodeIgniter 各自釘定一個受支援的範圍,因此「各種框架」指的是各框架的受支援版本,而非每一個歷史版本;請將各套件自己的文件視為其 API 的權威依據。第二,這些橋接是框架轉接層,而非算繪後端。若一份文件需要完整的瀏覽器版面引擎,那是一個與「由哪個框架呼叫引擎」彼此獨立的轉譯器選擇。
相關文件
標題為「相關文件」的區段- 整合決策指南——當你需要做抉擇而非統一時,這份「使用情境對應套件」的地圖,涵蓋轉譯器與 Connect 服務面。
- 開放核心,不被綁定——為什麼引擎才是資產、橋接是薄的,因此統一不會把你困住。
- HTML 管線——行程內引擎涵蓋哪些範圍,讓你知道何時瀏覽器轉譯器才是另一個問題。
- PHP 8.4 基礎——每個橋接與獨立路徑共享的執行環境底線。
詞彙表
標題為「詞彙表」的區段- 核心引擎(Core engine)——
nextpdf/core,與框架無關的 PDF 2.0 引擎,每個橋接與獨立路徑都建立於其上。 - 框架橋接(Framework bridge)——一個整合套件(Laravel、Symfony、CodeIgniter),把引擎調整為某框架的慣用語——facade、factory、回應、佇列化 job——而不改變其能力。
- 獨立路徑(Standalone path)——直接使用核心引擎,不經任何框架,由你自己建構一個
Document;這是 CLI 工具、常駐程式與函式庫的路線。 - 可丟棄文件(Disposable document)——用過即丟的
Document契約:建構、輸出、丟棄。每次容器解析都回傳一份全新的,因此在長壽命 worker 中不會有狀態在請求之間洩漏。 - PAdES——PDF Advanced Electronic Signatures,ETSI 的 PDF 簽署設定檔系列。基準簽署(B-B 與 B-T)內建於 Core;長期驗證(B-LT 與 B-LTA)屬於進階版本的能力。任一者都可透過任何表面取用,在簽署相關頁面有深入說明。