契約:41 個公開介面(SPI)
NextPDF\Contracts 是公開的 service-provider interface(SPI,服務提供者介面):src/Contracts/ 之下共有 41 個介面與列舉,每個都帶有明確的 @stability 標記與向後相容承諾。擴充套件、Framework(框架)橋接器,以及 Pro 與 Enterprise 版本都針對這些型別撰寫程式,絕不直接依賴具體類別。
composer require nextpdf/core:^3概念總覽
標題為「概念總覽」的區段引擎將兩個介面層分開。src/Core/、src/Html/ 與 src/Writer/ 之下的具體類別不承諾相容性,可能在各個次要版本之間自由變動。Contracts 命名空間則相反:它是一組精選型別,其簽章會依各自宣告的穩定度層級凍結。引擎以外的一切都只依賴這個命名空間,不再往下探入具體實作。這包含 Laravel、Symfony 與 CodeIgniter 橋接器、compat-tcpdf shim(相容層)、NextPDF Server,以及 Pro 與 Enterprise 版本。
每個契約都會在其 PHPDoc 中宣告四個層級之一。stable 契約在次要或修補版本中不接受任何破壞性變更。新方法只會連同預設實作一起加入。experimental 契約可能在次要版本中變更,但會附上棄用通知。deprecated 契約會指明其替代型別。少數型別僅作為契約存在,例如 StreamingWriterInterface 與 CursorInterface。這類型別已發布並凍結,但尚未隨附任何正式環境實作。
權威的層級清單是 docs/extension-points.json(資訊清單版本 3.0.0,橫跨 Contracts 與 Event 共 67 個已發布的擴充點)。可由機器驗證的測試 tests/Unit/Contracts/StabilityContractTest.php 會讀取該資訊清單,並在五種情況下讓建置失敗。第一種是清單列出的型別缺漏。第二種是反射取得的類型與資訊清單不一致。第三種是 @stability PHPDoc 標記與資訊清單發生偏移。第四種是 src/Contracts/ 之下有契約,卻未出現在資訊清單中。第五種是 @internal 型別洩漏進其中。契約介面層一旦發生偏移,就會被偵測出來。
契約分為九個領域。每個領域都有專屬頁面:文件建構、簽章、條碼編碼、字體排印、安全政策、擷取、可觀測性與串流。這樣的切分對應到整合者採用引擎的方式。你會依賴文件契約來產生 PDF,依賴簽章契約來加入簽章,也會依賴安全政策契約來約束不受信任的 HTML。
在整個引擎中,resolve(解析)選用實作都遵循同一種模式。Core 會以 class_exists() 檢查具體類別是否存在,再將它轉型為對應契約。LtvManagerInterface 與 PdfAManagerInterface 就是以這種方式解析其 Pro 實作。因此 Core 維持 Apache-2.0 授權,且不硬性依賴商業程式碼。
API 介面層
標題為「API 介面層」的區段| 契約 | 類型 | 穩定度 | 起始版本 | 領域 |
|---|---|---|---|---|
PdfDocumentInterface | 介面 | 穩定 | 1.0.0 | 文件 |
DocumentFactoryInterface | 介面 | 穩定 | 1.7.0 | 文件 |
ResettableService | 介面 | 穩定 | 1.7.0 | 文件 |
OutputDestination | 列舉 | 穩定 | 1.0.0 | 文件 |
Orientation | 列舉 | 穩定 | 1.0.0 | 文件 |
Alignment | 列舉 | 穩定 | 1.0.0 | 文件 |
SignerInterface | 介面 | 穩定 | 1.0.0 | 簽章 |
HsmSignerInterface | 介面 | 穩定 | 1.0.0 | 簽章 |
DeferredSignerInterface | 介面 | 實驗性 | 3.0.0 | 簽章 |
TimestampProviderInterface | 介面 | 實驗性 | 3.0.0 | 簽章 |
LtvManagerInterface | 介面 | 穩定 | 1.10.0 | 簽章 |
CryptoPolicyInterface | 介面 | 穩定 | 1.9.0 | 簽章 |
Barcode1DEncoderInterface | 介面 | 穩定 | 1.0.0 | 條碼 |
Barcode2DEncoderInterface | 介面 | 穩定 | 1.0.0 | 條碼 |
BarcodeEncoderInterface | 介面 | 穩定 | 3.0.0 | 條碼 |
Gs1DataParserInterface | 介面 | 穩定 | 1.0.0 | 條碼 |
FontRegistryInterface | 介面 | 穩定 | 1.7.0 | 字體排印 |
TextPreprocessorInterface | 介面 | 穩定 | 1.9.0 | 字體排印 |
HtmlSecurityPolicyInterface | 介面 | 穩定 | 3.1.0 | 安全政策 |
ExternalResourcePolicyInterface | 介面 | 穩定 | 4.0.0 | 安全政策 |
InspectorInterface | 介面 | 實驗性 | 2.2.0 | 擷取 |
EmbeddingServiceInterface | 介面 | 實驗性 | 2.1.0 | 擷取 |
VectorIndexInterface | 介面 | 實驗性 | 2.1.0 | 擷取 |
JobNotificationInterface | 介面 | 實驗性 | 2.2.0 | 可觀測性 |
SpectrumInterface | 介面 | 實驗性 | 2.1.0 | 可觀測性 |
StreamingWriterInterface | 介面 | 實驗性 | 3.1.0 | 串流 |
CursorInterface | 介面 | 實驗性 | 3.1.0 | 串流 |
此表格列出主要契約。其餘型別——value-object DTO(TextSegment、TextPreprocessResult)、EInvoice 子命名空間、行為列舉(DegradationPolicy、UnderlineStyle),以及匯入契約(ImportedFormObjectInterface、EmbeddedPdfObjectInterface、ChromeRenderResultInterface)——都記錄在 另見所列的領域頁面中。完整的機器可讀清單是 docs/extension-points.json,並鏡像同步到 .ai/contracts-map.md。
程式碼範例——快速上手
標題為「程式碼範例——快速上手」的區段<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
$doc = Document::createStandalone();$doc->setTitle('Hello World');$doc->addPage();$doc->setFont('helvetica', '', 24);$doc->cell(0, 15, 'Hello, NextPDF!', newLine: true);$doc->save(__DIR__ . '/output/01-hello-world.pdf');Document::createStandalone() 會回傳一個具體的 Document,它滿足 PdfDocumentInterface。請在你自己的服務中以介面作為型別提示,讓引擎內部維持可替換。
程式碼範例——正式環境
標題為「程式碼範例——正式環境」的區段<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\DocumentFactory;use NextPDF\Core\PdfFactory;use NextPDF\Graphics\ImageRegistry;use NextPDF\Typography\FontRegistry;
// Created once at process boot in a RoadRunner/Swoole/Octane worker.$fontRegistry = new FontRegistry();$imageRegistry = new ImageRegistry(maxCacheBytes: 50 * 1024 * 1024);$documentFactory = new DocumentFactory($fontRegistry, $imageRegistry);
$factory = PdfFactory::new() ->withCompress(true) ->withDocumentFactory($documentFactory);
for ($request = 1; $request <= 3; $request++) { $doc = $factory->create(); $doc->setTitle("Worker Request #{$request}"); $doc->addPage(); $doc->setFont('helvetica', 'B', 16); $doc->cell(0, 12, "Worker Request #{$request}", newLine: true); $doc->save(__DIR__ . "/output/14-worker-request-{$request}.pdf");}DocumentFactory 實作 DocumentFactoryInterface。它會持有行程生命週期等級的 FontRegistryInterface 與 ImageRegistryInterface 單例,並把它們注入每個可丟棄的 Document,因此一個 worker 在數千個請求中只需剖析每個字體一次。
邊界情況與陷阱
標題為「邊界情況與陷阱」的區段- 僅契約型別可以編譯,但沒有任何執行期支援。
new無法用於StreamingWriterInterface或CursorInterface,因為目前還沒有任何類別實作它們。請把它們視為預先宣告的 API。 - 單一型別的真實來源是
@stabilityPHPDoc 標記。docs/extension-points.json是整組型別的真實來源。當兩者不一致時,StabilityContractTest就會失敗——別只改其中一邊來掩蓋這個不一致。 experimental在實務上不代表不穩定,而是代表相容性承諾較弱。在固定依賴某個契約之前,請先閱讀其bc_promise欄位(位於.ai/contracts-map.md)。- 標示為
@internal的類別永遠不是契約,即使其他套件在技術上能夠參照它。穩定度測試會拒絕任何出現在資訊清單中的@internal型別。 - 對
stable介面新增方法,對實作者而言是破壞性變更,除非該方法隨附預設實作。引擎透過新增介面來擴充能力,而不是擴張既有介面。
針對 Contracts 撰寫程式不會增加任何可量測的執行期成本:介面型別提示在連結時解析,而不是每次呼叫時解析。本頁 worker 範例的 performance_budget 為三份文件合計 1500 ms 牆鐘時間與 64 MB 峰值記憶體。第一個請求的字體剖析會主導這份預算。後續請求會重用 registry 快取,使契約相關的工作降到個位數毫秒。成本模型在每次契約派送上為 O(1);真正的工作在具體實作中,記錄於各領域頁面。
安全注意事項
標題為「安全注意事項」的區段SPI 同時也是一道安全邊界。HtmlSecurityPolicyInterface 與 ExternalResourcePolicyInterface 是預設拒絕的契約,會在不受信任的 HTML 抵達 renderer(渲染器)之前約束它能做的事。CryptoPolicyInterface 會把關簽章與加密所用的演算法與金鑰強度選擇。因為這些是契約,整合者可以提供更嚴格的政策,而無須分叉引擎。任何與安全相關的政策都請固定依賴 stable 層級。實驗性政策契約可能在各個次要版本之間改變形態。簽章與安全政策領域頁面會載明完整的威脅模型與規範性參考。
符合性
標題為「符合性」的區段本總覽不作任何直接的規範性主張;每個領域頁面會建立自己的 citations 區塊。簽章契約對應到 ISO 32000-2 §12.8(數位簽章)與 ETSI EN 319 142(PAdES 基準)。PDF/A 管理器對應到 ISO 19005-4。關於條款層級的符合性表格,請參閱簽章、安全政策與擷取頁面。
商業脈絡
標題為「商業脈絡」的區段Pro 與 Enterprise 版本實作了數個 Core 契約背後的正式環境程式碼:LtvManagerInterface(長期驗證)、PdfAManagerInterface(PDF/A 強制)、Hardware Security Module(HSM,硬體安全模組)與延遲簽署者、條碼編碼器,以及嵌入與向量 Index(索引)契約。Core 發布並凍結介面;Premium 套件則隨附實作。這讓開源引擎維持 Apache-2.0 授權,同時讓商業部署享有可直接替換、且不需變更 API 的升級。
- 契約 / Document——PDF 文件、工廠與 registry 契約。
- 契約 / Signing——signer、HSM、時戳與 LTV 契約。
- 契約 / Security Policy——加密、HTML 與資源政策契約。
- 契約 / Typography——字體 registry 與文字前處理契約。
- 契約 / Extraction——inspector、PDF/A、嵌入與電子發票契約。
- Core——滿足這些契約的具體類別。
- Event——與
Contracts一同發布的事件 SPI 對應部分。