NextPDF Artisan 的啟動與探索
重點摘要
標題為「重點摘要」的區段Artisan 是一個純粹的 PSR-4 函式庫,沒有 service provider、沒有套件(bundle),也沒有 framework(框架)自動探索資訊清單。當它的類別能被自動載入的那一刻,就算完成「啟動」;所謂探索就是 Composer 的 PSR-4 對映表,僅此而已。
探索如何運作
標題為「探索如何運作」的區段套件的 composer.json 宣告了兩個 PSR-4 根目錄——NextPDF\Artisan\ → src/Artisan/,以及 NextPDF\Parser\ → src/Parser/。這裡沒有 extra.laravel、沒有 Symfony bundle 類別,也沒有 CodeIgniter registrar。啟動時不會掃描、註冊或掛載任何東西。
整合點位於 nextpdf/core 這一側。Document(透過 HasTextOutput concern)對外提供 writeHtmlChrome(),它會在執行階段執行一次 class_exists() 檢查,檢查對象是 NextPDF\Parser\PdfReader 與 NextPDF\Artisan\PageImporter。當這兩者都能透過自動載入器 resolve(解析)時,就能使用 Chrome 路徑。當它們無法解析時,core 會丟出版面例外,而不是發生致命錯誤。因此,所謂「探索」就是:Artisan 的類別是否已掛在自動載入器上?這個問題由 Composer 回答——完全不涉及任何 framework 機制。
這是刻意的設計。這個橋接層是 core 引擎跨越套件邊界取用的一項能力,而不是由 framework 管理的服務。因此,Artisan 在 Laravel、Symfony、CodeIgniter、CLI 指令稿或佇列 worker 中都能以相同方式使用,因為這些都不是必要條件。
啟動流程
標題為「啟動流程」的區段這裡沒有核心啟動程序(bootstrap kernel)、沒有指令註冊,也沒有延遲 provider 階段。第一次呼叫 writeHtmlChrome() 就是整個生命週期的進入點。
容器繫結
標題為「容器繫結」的區段Artisan 沒有 DI 容器,也不註冊任何繫結。各元件都是以建構式注入組成的純粹物件:建立一個 ChromeRendererConfig,把它傳給 ChromeHtmlRenderer,並視需要注入一個 PSR-3 logger 與一個自訂的 HtmlSecurityPolicyInterface。若使用宿主容器,請自行將 ChromeHtmlRenderer 註冊為單例——範例請見 /integrations/artisan/production-usage/.
無容器的服務解析
標題為「無容器的服務解析」的區段NextPDF 的部分能力(Premium 電子發票合約)通常會透過 framework 容器解析。Artisan 也會在無容器的環境中執行——CLI 工具、獨立指令稿、自訂執行器——因此它隨附了 EInvoiceServiceFactory:
| 方法 | 回傳值 | 何時為 null |
|---|---|---|
makeEmbedder() | EmbedderInterface(Pro 版) | 未安裝 Pro 層 |
makeValidator() | ValidatorInterface(Enterprise 版) | 未安裝 Enterprise 層 |
makeDefaultProfile() | ProfileInterface(EN16931,Pro 版) | 未安裝 Pro 層 |
makeSchematronRunner() | SchematronRunnerInterface(Enterprise 版) | 未安裝 Enterprise 層 |
每次呼叫都會回傳一個 全新 的執行個體(採用用完即棄語意——embed 與 validate 呼叫各自擁有一個可變的 XML 剖析(parse)脈絡,不得共用狀態)。這個工廠(factory)是提供給少數無容器情境的便利手段,而不是一個 service locator。建議做法仍是在建構階段組裝物件,並把它們當作建構式引數傳入。這種「找不到就回傳 null」的行為與 framework 包裝套件一致,因此同一份呼叫端程式碼無論是否有 Premium 都能執行。來源:src/Artisan/EInvoiceServiceFactory.php;整合測試位於 tests/Integration/Artisan/EInvoiceServiceFactoryIntegrationTest.php。
組態解析順序
標題為「組態解析順序」的區段這裡沒有組態檔的層疊機制。組態就是你傳給 ChromeRendererConfig 的內容:
- 明確的建構式引數,或者
ChromeRendererConfig::fromArray()會從宿主提供的陣列建立組態(採 snake-case 鍵;未設定的鍵會回退到建構式預設值;chrome_binary只有在是非空字串時才會套用)。
解析後的組態在 renderer(渲染器)的整個生命週期中都不可變。每個鍵的說明請見 /integrations/artisan/configuration 一節。
- 「這個橋接層可被探索到嗎?」——若
class_exists(\NextPDF\Artisan\PageImporter::class)為true,代表 Composer 的自動載入器已載入它;core 就會使用 Chrome 路徑。 - 「它啟動了嗎?」——這裡不存在會失敗的啟動程序;缺少的相依套件會在第一次呼叫
writeHtmlChrome()時以型別化例外浮現,其對映關係整理於 /integrations/artisan/troubleshooting/. - 無容器的 Premium 檢查——
EInvoiceServiceFactory::makeEmbedder() === null代表未安裝 Pro 層;開放原始碼渲染路徑不受影響。
另請參閱
標題為「另請參閱」的區段- 整合指南:/integrations/artisan/integration/
- 總覽:/integrations/artisan/overview/
- 組態:/integrations/artisan/configuration/
- 生產環境使用:/integrations/artisan/production-usage/
- 疑難排解:/integrations/artisan/troubleshooting/