排解 NextPDF Symfony bundle 的問題
重點摘要
標題為「重點摘要」的區段大多數問題都落在四個面向:探索、組態驗證、容器接線,或 Messenger 路由。以下各節會將症狀對應到 bundle 原始碼中負責驗證的行為,並提供一個主控台指令,用來確認修正是否生效。
bundle 未註冊
標題為「bundle 未註冊」的區段症狀:PdfFactory 無法自動注入,或 debug:container nextpdf 找不到任何項目。
原因:bundle 未加入 config/bundles.php。可能是 Flex 未執行,也可能是應用程式並未使用 Flex。
解法:
php bin/console debug:container nextpdf如果結果為空,請手動加入這個 bundle:
return [ NextPDF\Symfony\NextPdfBundle::class => ['all' => true],];自動註冊提示寫在 bundle 的 composer.json 裡,位於 extra.symfony.bundles 之下。它只會套用在啟用 Flex 的應用程式上。
啟動失敗,缺少 PHP 擴充套件
標題為「啟動失敗,缺少 PHP 擴充套件」的區段症狀:核心在啟動時拋出 RuntimeException,訊息提到 ext-mbstring 或 ext-zlib。
原因:這是 bundle 刻意設計的快速失敗(fail-fast)防護 NextPdfExtension::guardRequiredExtensions(),並不是缺陷。
解法:在 php.ini 中啟用指定的擴充套件,然後重新啟動執行環境。以下列指令確認:
php -m | grep -E 'mbstring|zlib'組態在建置期被拒絕
標題為「組態在建置期被拒絕」的區段症狀:出現 Symfony\Component\Config\Definition\Exception\InvalidConfigurationException,發生在 cache:clear 或 cache:warmup 期間。
原因:某個值落在 schema 允許範圍之外。這些限制來自 Configuration.php:
page_format必須是A4、A3、A5、Letter、Legal或Tabloid其中之一。orientation必須是P或L。unit必須是pt、mm、cm或in其中之一。pdfa必須是null、4、4e,或4f。image_cache_mb必須>= 0。
解法:列印合併後的組態,再修正有問題的鍵:
php bin/console debug:config nextpdfPDF/A 或簽章沒有作用
標題為「PDF/A 或簽章沒有作用」的區段症狀:pdfa 或 signature 區段已設定,但輸出卻是一般的 PDF。
原因:這些功能需要 nextpdf/premium。PdfFactory 只有在編譯期偵測到 Pro 擴充套件時,才會套用 PDF/A。編譯器流程(compiler pass)只有在 signature.enabled 為 true 且 signature.certificate 已設定時,才會註冊簽章器。
解法:確認 Premium 已安裝,且簽章器服務確實存在:
composer show nextpdf/premiumphp bin/console debug:container --show-private | grep -i signer若未安裝 Premium,bundle 會儲存該組態,但依設計會讓它維持不生效。bundle 文件所記載、搭配 Pro 的簽章能力,是基準的 B-B 設定檔。NextPDF Premium 文件則涵蓋 B-B 以外的其他設定檔。
Chrome 算繪沒有任何反應
標題為「Chrome 算繪沒有任何反應」的區段症狀:artisan 組態被忽略。
原因:Chrome CDP 算繪需要 nextpdf/artisan。編譯器流程會在編譯期以 class_exists 探測它。若缺少這個擴充套件,renderer(渲染器)就不會接線。
解法:
composer show nextpdf/artisanphp bin/console cache:clear # re-run the compile-time probe這項探測會在容器編譯期間執行。因此安裝完擴充套件後,要重新執行一次 cache:clear。
Messenger 處理器從未被呼叫
標題為「Messenger 處理器從未被呼叫」的區段症狀:GeneratePdfMessage 已派送,但沒有寫出任何 PDF。
原因與解法:
- 訊息未路由 — 新增一筆路由設定,將
NextPDF\Symfony\Message\GeneratePdfMessage對應到config/packages/messenger.yaml中的某個傳輸(transport),再啟動一個 worker(php bin/console messenger:consume <transport>)。 - 建構器不在定位器中 — 處理器會透過類別字串 ID,從 PSR-11 定位器(locator)取得建構器。容器識別碼是用來唯一識別某個項目的字串(PSR-11 §1.1.2)。如果定位器沒有註冊該建構器類別,處理器就會拋出
RuntimeException,指出所設定的建構器必須實作PdfBuilderInterface。請先註冊該建構器,再從定位器引用它。
檢查路由與定位器:
php bin/console debug:messengerphp bin/console debug:container --tag=container.service_locator訊息在派送時被 InvalidArgumentException 拒絕
標題為「訊息在派送時被 InvalidArgumentException 拒絕」的區段症狀:建構 GeneratePdfMessage 時拋出 InvalidArgumentException。
原因:訊息的資料傳輸物件(DTO)會驗證其輸入。已驗證的拒絕規則如下:
- 輸出路徑為空,或路徑中含有 null 位元組;
- 使用 stream-wrapper 協定(例如
php://...); - 含有
..的路徑穿越(path-traversal)片段(POSIX 或 Windows 分隔符皆然); - 輸出路徑未以
.pdf結尾(不分大小寫); builderClass不是語法上有效的類別名稱。
解法:傳入以 .pdf 結尾的絕對檔案系統路徑,以及真實、完整限定的建構器類別名稱。
文件帶有過時的資料
標題為「文件帶有過時的資料」的區段症狀:產生的 PDF 包含上一個請求的內容。
原因:某個 Document 實例在長時間執行的 worker 中跨請求被保留下來。文件服務刻意設為非共用,正是為了防止這種情況。
解法:在請求範圍內的方法中呼叫 PdfFactory::create()。切勿將回傳的文件儲存在共用服務上。
診斷指令參考
標題為「診斷指令參考」的區段php bin/console debug:container nextpdf # bundle servicesphp bin/console debug:config nextpdf # merged configurationphp bin/console debug:container --show-private # internal definitionsphp bin/console debug:messenger # message routingphp bin/console messenger:consume <t> -vv # verbose consume符合性
標題為「符合性」的區段每一列都是本頁提出的一項規範性主張,並釘選到一個來自受管 SDO 語料庫的完整 64 位十六進位 reference_id。 provenance(來源資訊)涵蓋語料庫資訊清單與檢索傳輸,記載於 _sidecars/rag-citations.yaml 一檔。
| 規範 | 條款 | 參考 ID | 主張 |
|---|---|---|---|
| PSR-11 | psr_11_container#1.1.2.p4 | 容器 has()/get() 識別碼合約 |
另請參閱
標題為「另請參閱」的區段- /integrations/symfony/install/ — 安裝與註冊。
- /integrations/symfony/configuration/ — 完整 schema 與限制。
- /integrations/symfony/boot-and-discovery/ — 探索與啟動順序。
- /integrations/symfony/security-and-operations/ — 安全標頭與路徑驗證。