排解 CodeIgniter 4 上的 NextPDF 問題
下列每個症狀,都對應到套件或 Framework(框架)原始碼中已驗證的成因。每一項也都提供具體修正方式。
探索與 resolve(解析)
標題為「探索與 resolve(解析)」的區段Services::pdfDocument() 回傳 null
標題為「Services::pdfDocument() 回傳 null」的區段在解析服務時,CodeIgniter 會掃描已探索到的 Config\Services 類別,尋找相符的方法。回傳 null 表示 framework 從未探索到套件的 Services 類別。
成因與對應修正如下:
- 自動探索已停用。 主機應用程式可能設定了
Config\Modules::$discoverInComposer = false。若是如此,請把nextpdf/codeigniter加進$composerPackages['only']。只有當這個旗標為true時,探索才會掃描 Composer 套件。 - 自動載入器已過時。 Composer 會把命名空間前綴
NextPDF\CodeIgniter\對映到它的基底目錄。過時的 classmap 會讓類別無法被找到(PSR-4 §x1.x3)。請執行composer dump-autoload。 $aliases清單被精簡了。 探索只會針對Config\Modules::$aliases中的項目執行。套件需要services,helper 則需要registrars。請把這兩個項目都還原回去。
pdf() 或 pdf_document() 未定義
標題為「pdf() 或 pdf_document() 未定義」的區段這些 helper 會透過兩種途徑註冊:套件的 Composer files 自動載入項目,以及套件的 Registrar。出現未定義函式錯誤,表示 files 項目尚未載入。
- 請執行
composer dump-autoload,重建files自動載入清單。 - 請確認
nextpdf/codeigniter有出現在vendor/composer/autoload_files.php之中。 - 暫時可直接呼叫
Services::pdf(false)或Services::pdfDocument(false)。這些 helper 只是上述呼叫的薄包裝層。
.env 覆寫值被忽略
標題為「.env 覆寫值被忽略」的區段解析覆寫值時,BaseConfig 會以小寫的短類別名稱作為前綴。這個類別是 NextPdf,所以前綴是 nextpdf。它不是 nextPdf,也不是 NextPdf。
- 請使用
nextpdf.fontsPath,不要使用nextPdf.fontsPath。 - 以小數點指定巢狀鍵:
nextpdf.signature.certificate。 - 完整限定的形式
NextPDF\CodeIgniter\Config\NextPdf.fontsPath也可以使用。
整個組態陣列回復成預設值
標題為「整個組態陣列回復成預設值」的區段當你擴充 NextPdf 類別並指派不完整的陣列時,整個陣列會被取代。因此,你覆寫的陣列務必提供其中每一個鍵。完整陣列範例請見 /integrations/codeigniter/configuration/.
執行階段錯誤
標題為「執行階段錯誤」的區段RuntimeException: NextPDF requires the ext-… PHP extension
標題為「RuntimeException: NextPDF requires the ext-… PHP extension」的區段字型登錄會在每個程序中各驗證一次 mbstring 與 zlib。它會拋出這個錯誤,並附上缺少的擴充功能名稱。請在執行時使用的 PHP 中安裝或啟用所指名的擴充功能。接著重新啟動 worker 或 PHP-FPM pool。
RuntimeException: NextPdf fontsPath contains invalid characters
標題為「RuntimeException: NextPdf fontsPath contains invalid characters」的區段字型登錄會拒絕這類 fontsPath:內含 stream wrapper(://)或 null 位元組。請把 fontsPath 設成單純的檔案系統路徑。不要讓它指向 php://、phar:// 或類似的包裝路徑。
回應問題
標題為「回應問題」的區段下載時檔名看起來不對
標題為「下載時檔名看起來不對」的區段PdfResponse 會淨化檔名。已驗證的行為如下:
- 空白或只含空白字元的檔名會變成
document.pdf。 - 沒有
.pdf(或.PDF)副檔名的名稱,會被加上.pdf。既有的.PDF會原樣保留。 - 非 ASCII 的名稱會產生一個 ASCII 後備值,以及一個 RFC 5987
filename*=UTF-8''…參數,因此現代瀏覽器會顯示原始名稱。這是預期行為,不是 bug。 - 路徑分隔符號、null 位元組,以及 CR/LF 都會被去除。
回應缺少安全標頭
標題為「回應缺少安全標頭」的區段每個 PdfResponse 回應都會帶有 X-Content-Type-Options、X-Frame-Options、Content-Security-Policy、X-Robots-Tag,以及 Referrer-Policy。如果它們在用戶端消失,表示有 proxy 或下游應用程式移除或覆寫了它們。請在你的反向 proxy 前後都檢查一次回應。
QueueException:推送工作時出現
標題為「QueueException:推送工作時出現」的區段佇列會把推送的工作名稱與 Config\Queue::$jobHandlers 的鍵做比對,並拒絕任何未註冊的名稱。請以名稱鍵註冊該工作,然後推送那個名稱:
public array $jobHandlers = ['generate-pdf' => GeneratePdfJob::class];
// dispatch\service('queue')->push('pdf-queue', 'generate-pdf', [...]);把 GeneratePdfJob::class 當成工作名稱推送會失敗。第二個引數是名稱鍵,不是類別字串。
InvalidArgumentException:由工作拋出
標題為「InvalidArgumentException:由工作拋出」的區段工作在開始任何作業之前會先驗證它的酬載。已驗證的拒絕情形與對應訊息如下:
| 成因 | 訊息片段 |
|---|---|
builder 缺少、為空,或不是字串 | non-empty static callable string |
builder 不屬於 App\PdfBuilders | not allowed |
builder 格式看似正確但不可呼叫 | not a valid callable |
outputPath 缺少或為空 | non-empty string |
outputPath 不位於 WRITEPATH/pdfs/ | outside of allowed directory |
outputPath 的結尾不是 .pdf | must end with .pdf |
請修正酬載,讓 builder 成為一個 App\PdfBuilders\<Class>::<method> 靜態 callable。並確認輸出路徑會解析到 WRITEPATH/pdfs/ 之內,且帶有 .pdf 副檔名。
class … BaseJob not found
標題為「class … BaseJob not found」的區段codeigniter4/queue 是套件開發環境專用的相依套件。執行 worker 的應用程式必須直接引入它:
composer require codeigniter4/queuecomposer show nextpdf/codeigniter— 確認套件已成功解析。composer dump-autoload— 重建探索與 helper 的自動載入。php spark routes— 確認你的 PDF 路由已註冊。- 最快的探索檢查方式,是寫一個控制器來呼叫
Services::pdfDocument(false),並斷言其結果是一個Document。
符合性
標題為「符合性」的區段- 類別到路徑的對映 — 與探索失敗相關(PSR-4 Autoloader §x1.x3)。
另請參閱
標題為「另請參閱」的區段- /integrations/codeigniter/install/ — 探索需求。
- /integrations/codeigniter/configuration/ —
.env前綴與陣列覆寫規則。 - /integrations/codeigniter/production-usage/ — 正確的佇列註冊方式。
- /integrations/codeigniter/boot-and-discovery/ — 探索順序。