跳到內容

NextPDF Laravel 整合總覽

這個 nextpdf/laravel 套件會將 NextPDF PDF 引擎整合到 Laravel 12 應用程式,並替你註冊好容器繫結。它附帶一個 Pdf facade、一個 PdfResponse HTTP 輔助類別,以及一個可排入佇列的 GeneratePdfJob。Laravel 會自動探索這個套件,因此你不必手動註冊。

Terminal window
composer require nextpdf/laravel

Composer 版本限制為 nextpdf/core: ^3.0 || ^5.2。此套件還需要 laravel/framework: ^12.0php: >=8.4 <9.0。完整步驟,包括發布設定與選用擴充功能,請見 /integrations/laravel/install/.

此套件是 Laravel 服務容器與不依賴特定 Framework(框架)的 NextPDF core 之間一層很薄的銜接。它並不重新實作 PDF 產生功能。它的做法是把 core 的 NextPDF\Core\Document 模型轉接到 Laravel 的生命週期、組態、佇列與 HTTP 各層。

下圖說明一個請求如何從你的應用程式碼出發,經由此套件,最後進入共用的 core 登錄表。

NextPDF Laravel request and render flowA request resolves a fresh document from the container, which the package adapts onto the shared font and image registries before HTTP or queue output.

Your Laravel app

Pdf facade

Laravel service container

NextPdfServiceProvider (deferred)

DocumentFactory (singleton)

Document (fresh per resolve)

FontRegistry (singleton, locked)

ImageRegistry (singleton, LRU)

PdfResponse (HTTP)

GeneratePdfJob (queue worker)

NextPDF Laravel request and render flow

自動載入對映只有一筆 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,因此每個請求的可變狀態絕不會跨請求外洩。

類別公開進入點回傳用途
NextPdfServiceProviderregister()boot()provides()void / array容器繫結、組態發布、延遲項目清單
Facades\Pdf靜態 proxy(addPage()cell()save() 等)static / mixed每次呼叫都解析出一個 PdfDocumentInterface 實例
Http\PdfResponseinline()download()streamInline()streamDownload()Response / StreamedResponse附帶 OWASP 標頭的 HTTP 回應
Jobs\GeneratePdfJobdispatch()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 時才會解析
resource: README.md Quick Start (verified against src/Laravel/Facades/Pdf.php)
<?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/.

resource: src/Laravel/Http/PdfResponse.php (download factory)
<?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() 項目時,這些繫結才會出現。
  • SignerInterfaceTsaClient 在你尚未設定簽署或時間戳記機構時,依設計會解析為 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: nosniffX-Frame-Options: DENYContent-Security-Policy: default-src 'none'X-Robots-Tag,以及 Referrer-Policy: no-referrerGeneratePdfJob 會在 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/ — 威脅模型與部署設定