13.x とFramework v13.37.0 の実装を参照し、パッケージ開発の基礎を掘り下げます。通常のテンプレート記法はBlade、ビューの名前空間と公開はパッケージビューの上書きと更新を参照してください。
登録・コンパイル・実行を区別する
Blade::directive() に渡すコールバックは、表示する値ではなく生成するPHPコードの文字列を返します。引数の $expression も、評価済みの値ではなくテンプレートに書かれたPHP式です。
view:cache でもコンパイルが行われます。ディレクティブの生成用コールバックでは、現在のユーザーの取得、DBへの書き込み、外部API呼び出しなどを行わない設計にします。
パッケージ固有の名前で登録する
例として、配送コードの前に設定されたラベルを表示する@acmeCourierLabel($code) を提供します。ComposerのPSR-4設定で Acme\Courier\ を src/ に対応させ、プロバイダーを自動検出または手動で登録することを前提にします。
src/CourierServiceProvider.php
courier.label は文字列、courier.enabled はbooleanという設定の契約にします。設定ファイルの配布やマージはパッケージ設定のマージとキャッシュを参照してください。
登録は通常のプロバイダーの boot() で行い、runningInConsole() の条件では囲みません。HTTPでの描画と、Artisanの view:cache の両方で同じ拡張が必要です。Blade拡張だけを登録するプロバイダーを、別サービスの解決まで起動しない遅延プロバイダーにすることも避けます。
引数は値ではなく式として受け取る
$code です。生成されるPHPは次の形になります。
config() と $code の評価は、このPHPを実行する時点です。コールバック自身が config() を読んで固定の文字列を返す実装とは異なります。
確認した callCustomDirective() は、外側の丸括弧を除去して式をtrimし、コールバックへ渡します。引数をPHPの値に変換したり、個別の引数へ分割したりはしません。この例は必須の式を1つ渡す記法として公開します。
複数引数を扱う場合、単純にカンマで explode() しないでください。配列、メソッド呼び出し、文字列リテラルの中にもカンマが含まれます。属性や複雑なHTMLを扱いたい場合は、Bladeコンポーネントとして提供する方が責務を分けやすくなります。
名前の衝突も互換性の問題になる
directive() は、名前をキーとしてハンドラーを配列へ保存します。同じ名前なら以前の登録を上書きし、compileStatement() は組み込みの変換メソッドより独自ディレクティブを先に選びます。公式テストにも、独自登録で foreach を上書きするケースがあります。
label や enabled といった一般名、組み込みの名前を避け、パッケージ固有の接頭辞を付けます。利用者がテンプレートで使う名前と引数は公開APIとして扱い、変更時は移行手順を提供します。
条件分岐はBlade::ifで実行時に判定する
上のプロバイダーで登録した条件は、次のように使えます。Blade::if() は、条件コールバックを保存したうえで、開始・unless・else・終了用のディレクティブを登録します。この例の開始部分は、次のPHPに変換されます。
check() から実行時に呼ばれます。コンパイル時に結果のtrue・falseを固定する処理ではありません。コンパイル済みビューを使うHTTPプロセスでも、条件のコールバック登録が必要です。
この記法は表示の切り替えであり、配送操作の認可ではありません。アクセス制御はルートや操作側でも実施します。
パッケージ更新でビューが自動再生成されるとは限らない
確認したCompiler::isExpired() は、キャッシュの有無と、設定に応じて元ビューとコンパイル済みファイルの更新時刻を調べます。プロバイダーに書かれたディレクティブの変更を依存ファイルとして追跡する処理ではありません。
公式ドキュメントも、ディレクティブのロジックを変更した後は
view:clear でキャッシュを削除するよう案内しています。利用アプリケーションのデプロイ工程で、更新したパッケージと利用者のビューをそろえた後に実行します。
view:cache は本番で事前コンパイルする場合に実行します。パッケージの boot() から毎回キャッシュを消したり、インストール時に利用アプリケーションのデプロイ工程を無断で書き換えたりしないでください。設定キャッシュの更新や常駐プロセスの再読み込みも、利用環境の通常のデプロイ手順に従います。
コンパイル結果と描画結果を別々に検証する
まずは、上記プロバイダーが登録されたテスト用Laravelアプリケーションで、生成されるPHPを検証します。次はTests\TestCase を継承するFeatureテストに追加するメソッドです。
関連ページ
パッケージビューの上書きと更新
名前空間の検索順序と、公開済みテンプレートを保守する方法を確認します。
パッケージのキャッシュとoptimizeへの統合
独自キャッシュの構築・削除をデプロイ工程へ統合する方法を確認します。