NextPDF Laravel 整合總覽
這個 nextpdf/laravel 套件會將 NextPDF PDF 引擎整合到 Laravel 12 應用程式,並替你註冊好容器繫結。它附帶一個 Pdf facade、一個 PdfResponse HTTP 輔助類別,以及一個可排入佇列的 GeneratePdfJob。Laravel 會自動探索這個套件,因此你不必手動註冊。
composer require nextpdf/laravelComposer 版本限制為 nextpdf/core: ^3.0 || ^5.2。此套件還需要 laravel/framework: ^12.0 與 php: >=8.4 <9.0。完整步驟,包括發布設定與選用擴充功能,請見 /integrations/laravel/install/.
概念說明
標題為「概念說明」的區段此套件是 Laravel 服務容器與不依賴特定 Framework(框架)的 NextPDF core 之間一層很薄的銜接。它並不重新實作 PDF 產生功能。它的做法是把 core 的 NextPDF\Core\Document 模型轉接到 Laravel 的生命週期、組態、佇列與 HTTP 各層。
下圖說明一個請求如何從你的應用程式碼出發,經由此套件,最後進入共用的 core 登錄表。
自動載入對映只有一筆 PSR-4 項目。PSR-4 是 PHP 自動載入的標準建議,其前綴 NextPDF\Laravel\ 對映到 src/Laravel/。依 PSR-4,命名空間前綴會對應一個基底目錄,剩餘的類別名稱再對映到該目錄底下的檔案路徑(PSR-4 §3)。此前綴底下有四個正式提供的類別:
NextPDF\Laravel\NextPdfServiceProvider— 註冊繫結並發布組態。NextPDF\Laravel\Facades\Pdf— 一個靜態 proxy(轉發類別),會從容器 resolve(解析)一份全新的 document。NextPDF\Laravel\Http\PdfResponse— 一個工廠,可產生 inline、下載與串流式 PDF 回應,並附帶一組固定的安全標頭。NextPDF\Laravel\Jobs\GeneratePdfJob— 一個可排入佇列的 job,會在 worker 上建立並儲存 PDF。
此服務提供者實作了 DeferrableProvider,因此只有在你解析其中一個已宣告的項目時,它才會註冊繫結。這種延遲機制讓框架的啟動路徑保持輕量。此提供者的 provides() 方法會列出延遲載入的項目,容器則讀取這份清單,把每個鍵對映回該提供者。
解析會遵循容器契約:當繫結存在時,解析該識別碼就會回傳已註冊的項目。PSR-11 是 PHP 容器互通性的標準建議,它指出對同一個識別碼連續呼叫兩次 get(),可能依繫結策略而回傳不同的值(PSR-11 §1.1.2)。NextPDF 刻意倚賴這項行為。登錄表是單例,所以每次解析都回傳同一個實例;document 則採工廠繫結,所以每次解析都回傳一份全新的實例。完整的繫結生命週期表,請見 /integrations/laravel/boot-and-discovery/.
此架構針對長壽命的 worker 設計,例如 Octane、RoadRunner 與 Swoole。font registry 是行程生命週期的單例:套件只暖機一次便將其鎖定,因此任何請求都無法更動共用的字型狀態。image registry 是行程生命週期的單例,搭配一個有界的最近最少使用(LRU)快取。由於套件總是從 DocumentFactory 建立全新的 document,因此每個請求的可變狀態絕不會跨請求外洩。
API 介面
標題為「API 介面」的區段| 類別 | 公開進入點 | 回傳 | 用途 |
|---|---|---|---|
NextPdfServiceProvider | register()、boot()、provides() | void / array | 容器繫結、組態發布、延遲項目清單 |
Facades\Pdf | 靜態 proxy(addPage()、cell()、save() 等) | static / mixed | 每次呼叫都解析出一個 PdfDocumentInterface 實例 |
Http\PdfResponse | inline()、download()、streamInline()、streamDownload() | Response / StreamedResponse | 附帶 OWASP 標頭的 HTTP 回應 |
Jobs\GeneratePdfJob | dispatch()、handle()、then()、catch()、failed() | PendingDispatch / void / self | 排入佇列的 PDF 產生 |
由提供者繫結的容器鍵:
| 鍵 | 生命週期 | 解析為 |
|---|---|---|
NextPDF\Contracts\FontRegistryInterface(別名 FontRegistry) | 單例,已鎖定 | NextPDF\Typography\FontRegistry |
NextPDF\Graphics\ImageRegistry | 單例,LRU 有界 | ImageRegistry |
NextPDF\Contracts\DocumentFactoryInterface(別名 DocumentFactory) | 單例 | NextPDF\Core\DocumentFactory |
Psr\Http\Client\ClientInterface | 單例 | SecurityAwareHttpClient,包裹 CurlHttpClient |
NextPDF\Security\Timestamp\TsaClient | 受限範圍 | TsaClient,或在沒有設定 TSA URL 時為 null(即無 TSA 用戶端) |
NextPDF\Contracts\SignerInterface | 工廠 | DigitalSigner,或在停用簽署時為 null(即未啟用簽署) |
NextPDF\Contracts\PdfDocumentInterface(別名 nextpdf) | 工廠 | NextPDF\Core\Document |
NextPDF\Contracts\EInvoice\{Embedder,Validator,Profile,SchematronRunner}Interface | 工廠 | 只有在安裝了 nextpdf/premium 時才會解析 |
程式碼範例 — 快速上手
標題為「程式碼範例 — 快速上手」的區段<?php
declare(strict_types=1);
use NextPDF\Laravel\Facades\Pdf;
Pdf::addPage();Pdf::cell(0, 10, 'Hello from Laravel', newLine: true);Pdf::save(storage_path('app/hello.pdf'));以 controller 為範圍且可直接執行的範例,請見 /integrations/laravel/quickstart/.
程式碼範例 — 正式環境
標題為「程式碼範例 — 正式環境」的區段正式環境的寫法會從容器解析 document 契約,而非透過 facade;這讓呼叫點更明確,也更易於測試。包含相依性注入(DI)與錯誤處理的完整 controller,請見 /integrations/laravel/production-usage/.
<?php
declare(strict_types=1);
use NextPDF\Contracts\PdfDocumentInterface;use NextPDF\Laravel\Http\PdfResponse;
$document = app(PdfDocumentInterface::class);$document->addPage();$document->cell(0, 10, 'Invoice', newLine: true);
return PdfResponse::download($document, 'invoice.pdf');邊界情況與陷阱
標題為「邊界情況與陷阱」的區段- 此提供者採延遲載入,因此解析不相關的容器鍵並不會啟動 NextPDF。只有當你請求其中一個
provides()項目時,這些繫結才會出現。 SignerInterface與TsaClient在你尚未設定簽署或時間戳記機構時,依設計會解析為null。你的程式碼必須對結果進行 null 檢查,不要假設實例一定存在。- e-invoice 契約繫結一律會註冊,但它們只會解析為 Premium 的具體實作,而這些實作只有在安裝了
nextpdf/premium時才存在。在沒有 Premium 的情況下解析它們會引發 class-not-found 錯誤,且錯誤出現在首次解析時,而非啟動時。 - 此 facade 每次解析都回傳一份全新的 document。假設同一個請求中有兩次
Pdf::靜態呼叫,中間隔著一個Pdf::clearResolvedInstances():這兩次呼叫會操作不同的 document。
提供者註冊以 O(1) 時間執行。此提供者只繫結閉包,不建構重量級物件,因此建構成本會延遲到首次解析時才發生。font registry 的暖機以 O(f) 時間執行,其中 f 是預先載入的字型檔案數量,且每個 worker 行程只執行一次。這樣的時機安排,能在長壽命的 worker 中分攤首次請求的延遲。本總覽頁的記憶體預算記錄在 front-matter 欄位 performance_budget 中。
安全性備註
標題為「安全性備註」的區段PdfResponse 會套用一組來自開放全球應用程式安全專案(OWASP)的固定標頭。這些標頭是 X-Content-Type-Options: nosniff、X-Frame-Options: DENY、Content-Security-Policy: default-src 'none'、X-Robots-Tag,以及 Referrer-Policy: no-referrer。GeneratePdfJob 會在 worker 端驗證它的輸出路徑,這項檢查可降低序列化負載遭竄改的風險。完整的威脅模型與部署設定,請見 /integrations/laravel/security-and-operations/.
符合性
標題為「符合性」的區段| 主張 | 來源 | 條款 | 參考 ID |
|---|---|---|---|
| 容器解析/生命週期語意 | PSR-11 容器 | §1.1.2 | |
| PSR-4 自動載入前綴對映 | PSR-4 自動載入器 | §3 |
商業脈絡
標題為「商業脈絡」的區段安裝 nextpdf/premium 後,同一個提供者會公開更多功能:數位簽署(PAdES B-B)、PDF/A 封存,以及 e-invoice 契約繫結。此提供者透過完全相同的容器鍵公開這些功能,因此本頁所記載的 Core 套件不需任何程式碼變更即可採用這些功能。詳情請見
https://nextpdf.dev/get-license/?intent=laravel-signing。
另請參閱
標題為「另請參閱」的區段- /integrations/laravel/install/ — 安裝步驟與選用擴充功能
- /integrations/laravel/quickstart/ — 可直接執行的 controller 範例
- /integrations/laravel/configuration/ — 每個 config 鍵皆對照驗證
config/nextpdf.php - /integrations/laravel/production-usage/ — 以 DI 接線的 controller、錯誤處理與佇列
- /integrations/laravel/boot-and-discovery/ — 自動探索與繫結生命週期
- /integrations/laravel/security-and-operations/ — 威脅模型與部署設定