メインコンテンツへスキップ

このページについて

パッケージ開発の基礎では composer.jsonextra.laravel セクションを書けばサービスプロバイダーとファサードが自動登録されることを紹介しました。このページではその裏側、Illuminate\Foundation\PackageManifest クラスがどのように動作しているかをソースコードレベルで解説します。
このページはパッケージ開発の基礎の姉妹ページです。自動検出の基本的な使い方を先に読むことをおすすめします。

自動検出の仕組み全体像

PackageManifest クラス

自動検出の中核は Illuminate\Foundation\PackageManifest です。以下がフレームワーク13.x時点の実装(要約)です。
ポイントは次の3つです。
  • マニフェストは一度読み込むとメモリにキャッシュされる$this->manifest プロパティ)。1リクエスト内で複数回 providers() を呼んでもファイルI/Oは1回だけ。
  • マニフェストファイルが存在しない場合のみ build() が実行される。通常運用では毎回ビルドされるわけではない。
  • 実体は素朴なPHP配列を return するファイル(bootstrap/cache/packages.php)で、require するだけで読み込める最速の形式。

マニフェストのビルド処理

build() メソッドが実際に composer.json の情報を集約する部分です。
重要な点は、composer.json を直接パースするのではなく vendor/composer/installed.json を読んでいることです。これはComposerが composer install / composer update 実行時に生成する、インストール済み全パッケージのメタデータファイルです。各パッケージの composer.json に書かれた extra セクションがここに集約されているため、Laravel側はComposerの管理下にある情報だけを信頼して読み取ります。
installed.json は通常 .gitignore されているため、初回セットアップ時(vendor/ がない状態)では自動検出は機能しません。composer install の完了後に初めてキャッシュが構築されます。

dont-discover の2つの書き方

dont-discover はパッケージ側・アプリケーション側どちらの composer.json にも書けますが、意味が異なります。
パッケージ側のcomposer.json
アプリケーション側のcomposer.json
build() の実装を見ると、$ignore 配列は各パッケージの configuration['dont-discover']array_merge して蓄積しています。つまりパッケージ自身が「自分の依存パッケージの自動検出を無効化する」ことも技術的には可能です(例:内部で使っているサブパッケージのプロバイダーを重複登録させたくない場合)。ただし実務でよく使うのはアプリケーション側での無効化です。

dont-discover* を指定する

packagesToIgnore() が返す配列に * が含まれていると $ignoreAll = true となり、すべてのパッケージの自動検出を丸ごと無効化します。CIやテスト環境で自動検出のオーバーヘッドを避けたい場合や、bootstrap/providers.php で完全に手動管理したい場合に使います。

キャッシュファイルの実体

getCachedPackagesPath() は環境変数 APP_PACKAGES_CACHE があればそれを、なければ bootstrap/cache/packages.php を返します。
このファイルを直接開くと、単純な連想配列を return しているだけだとわかります。
パッケージ名がキーになっているため、php artisan package:discover の出力で「どのパッケージが検出されたか」を確認できます。

キャッシュが再構築されるタイミング

Illuminate\Foundation\ComposerScripts は3つのComposerイベントにフックしており、いずれも同じ clearCompiled() を呼びます。
つまり composer install / composer update / composer dump-autoload のいずれを実行しても、設定キャッシュ・サービスキャッシュ・パッケージキャッシュがまとめて削除されます。次にLaravelが起動したタイミングで PackageManifest::build() が走り、installed.json の最新状態から再構築されます。 これは composer.jsonscripts に登録されている、標準的なLaravelプロジェクトの挙動です。
Laravelアプリのcomposer.json(抜粋)

php artisan package:discover で手動再構築

キャッシュが古いままになっている、あるいはComposerを経由せずに vendor/ を直接変更したような場合は、package:discover コマンドで手動再構築できます。
このコマンドの実体は非常に薄いラッパーです。
$manifest->build() を呼んで結果を出力するだけで、コマンド固有のロジックはほぼありません。CIパイプラインで composer install --no-scripts を使っている場合など、Composerイベントが発火しない状況ではこのコマンドを明示的に呼ぶ必要があります。
パッケージのテストで Orchestra Testbench を使う場合、Testbenchは独自の vendor/bin/testbench package:discover コマンドを提供しています。詳細はTestbenchでのパッケージテストを参照してください。Artisanの package:discover とは別物で、Testbench専用のスケルトンアプリ向けにマニフェストを構築します。

デプロイ時の注意点

本番デプロイでは composer install --no-dev --optimize-autoloader を実行するのが一般的ですが、--no-scripts を付けている場合はパッケージキャッシュが更新されません。デプロイスクリプトに明示的な再構築ステップを入れておくと安全です。
順序も重要です。package:discoverconfig:cache より前に実行してください。設定キャッシュが先に作られると、後から追加されたパッケージ設定(mergeConfigFrom で登録される設定など)が反映されない場合があります。

まとめ

  • 自動検出は composer.json の静的な内容ではなく、Composerが生成する vendor/composer/installed.json を読み取って動作する。
  • 結果は bootstrap/cache/packages.php にプレーンなPHP配列としてキャッシュされ、require だけで高速に読み込まれる。
  • キャッシュは composer install/update/dump-autoload の各イベントで自動的に削除され、次回起動時に再構築される。
  • --no-scripts でComposerを実行する環境では php artisan package:discover を明示的に呼ぶ必要がある。
  • dont-discover* を指定すると自動検出全体を無効化できる。

関連ページ

最終更新日 2026年7月18日