NextPDF Artisan のブートとディスカバリー
Artisan は素の PSR-4 ライブラリであり、サービスプロバイダー、バンドル、フレームワークの自動ディスカバリーマニフェストはいずれもありません。クラスがオートロード可能になった時点で「ブート」します。ディスカバリーとは Composer の PSR-4 マップそのものであり、それ以上ではありません。
ディスカバリーの仕組み
「ディスカバリーの仕組み」という見出しのセクションパッケージの composer.json は 2 つの PSR-4 ルートを宣言します。NextPDF\Artisan\ → src/Artisan/ と NextPDF\Parser\ → src/Parser/ です。extra.laravel も、Symfony のバンドルクラスも、CodeIgniter のレジストラーもありません。ブート時にスキャン、登録、フックを行うものは何もありません。
統合ポイントは nextpdf/core 側にあります。Document(HasTextOutput コンサーン経由)は writeHtmlChrome() を公開します。これは実行時に class_exists() チェックを行い、NextPDF\Parser\PdfReader と NextPDF\Artisan\PageImporter が存在するかを確認します。両方がオートローダー経由で解決(resolve)されると、Chrome パスが利用可能になります。解決されない場合、core は致命的なエラーではなく、レイアウト例外を発生させます。したがって「ディスカバリー」とは、Artisan のクラスがオートローダーに載っているかどうかを指します。その判断を担うのは Composer であり、フレームワークの仕組みは一切関与しません。
これは意図的な設計です。このブリッジは、コアエンジンがパッケージ境界を越えて呼び出すケイパビリティであり、フレームワークが管理するサービスではありません。特定のフレームワークを必須にしないため、Laravel、Symfony、CodeIgniter、CLI スクリプト、キューワーカーのいずれでも、Artisan を同じように利用できます。
ブートシーケンス
「ブートシーケンス」という見出しのセクションブートストラップカーネルも、コマンド登録も、遅延プロバイダーフェーズもありません。最初の writeHtmlChrome() 呼び出しが、ライフサイクル全体のエントリーポイントです。
コンテナーバインディング
「コンテナーバインディング」という見出しのセクションArtisan には DI コンテナーがなく、バインディングも登録しません。コンポーネントは、コンストラクターインジェクションされる素のオブジェクトです。ChromeRendererConfig を構築して ChromeHtmlRenderer に渡し、必要に応じて PSR-3 ロガーやカスタムの HtmlSecurityPolicyInterface を注入します。ホスト側のコンテナーでは、ChromeHtmlRenderer をシングルトンとして手動で登録してください。例については、次を参照してください:/integrations/artisan/production-usage/。
コンテナーを使わないサービス解決
「コンテナーを使わないサービス解決」という見出しのセクション一部の NextPDF ケイパビリティ(Premium の e-invoice コントラクト)は、通常はフレームワークのコンテナーを通じて解決されます。Artisan はコンテナーを使わない環境(CLI ツール、スタンドアロンスクリプト、カスタムランナー)でも動作するため、EInvoiceServiceFactory を同梱しています。
| メソッド | 戻り値 | 戻り値が null の条件 |
|---|---|---|
makeEmbedder() | EmbedderInterface(Pro) | Pro ティアの未インストール |
makeValidator() | ValidatorInterface(Enterprise) | Enterprise ティアの未インストール |
makeDefaultProfile() | ProfileInterface(EN16931、Pro) | Pro ティアの未インストール |
makeSchematronRunner() | SchematronRunnerInterface(Enterprise) | Enterprise ティアの未インストール |
各呼び出しは 新しい インスタンスを返します(一度きりの使用を前提とするセマンティクスです。embed と validate の呼び出しは可変の XML 解析コンテキストを保持するため、状態を共有してはなりません)。このファクトリーは、まれなコンテナーなしのケースに向けた便宜的な手段であり、サービスロケーターではありません。推奨パターンは、引き続きオブジェクトを構築時に組み立て、コンストラクター引数として渡すことです。存在しないときに null を返す動作はフレームワークのラッパーパッケージと同じであるため、同じ呼び出しコードが Premium の有無にかかわらず動作します。ソース:src/Artisan/EInvoiceServiceFactory.php。統合テストは tests/Integration/Artisan/EInvoiceServiceFactoryIntegrationTest.php で行われています。
設定の解決順序
「設定の解決順序」という見出しのセクション設定ファイルのカスケードはありません。設定とは、ChromeRendererConfig に渡したものそのものです。
- 明示的なコンストラクター引数。または
ChromeRendererConfig::fromArray()による、ホスト提供の配列からの解決(snake-case のキー。設定されていないキーはコンストラクターのデフォルトにフォールバックします。chrome_binaryは空でない文字列のときにのみ適用されます)。
解決された設定は、レンダラーのライフタイムを通じてイミュータブルです。すべてのキーについては、/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/