イントロダクション
パッケージは、Laravelに機能を追加するための主要な方法です。パッケージは、Carbonのような日付を処理するための優れた方法から、SpatieのLaravel Media LibraryのようなEloquentモデルにファイルを関連付けることができるパッケージまであります。
パッケージにはさまざまな種類があります。一部のパッケージはスタンドアロンです。つまり、どのPHPフレームワークでも機能します。CarbonとPHPUnitは、スタンドアロンパッケージの例です。これらのパッケージはいずれも、composer.json
ファイルでリクエストすることにより、Laravelで使用できます。
逆にLaravelと一緒に使用することを意図したパッケージもあります。こうしたパッケージはLaravelアプリケーションを高めることをとくに意図したルート、コントローラ、ビュー、設定を持つことでしょう。このガイドはLaravelに特化したパッケージの開発を主に説明します。
ファサード使用の注意
Laravelアプリケーションを作成する場合、コントラクトとファサードのどちらを使用しても、どちらも基本的に同じレベルのテスト容易性を提供するため、通常は問題になりません。ただし、パッケージを作成する場合、通常、パッケージはLaravelのすべてのテストヘルパにアクセスできるわけではありません。パッケージが一般的なLaravelアプリケーション内にインストールされているかのようにパッケージテストを記述できるようにしたい場合は、Orchestral Testbenchパッケージを使用できます。
パッケージディスカバリー
Laravelアプリケーションのconfig/app.php
設定ファイルには、Laravelがロードすべきサービスプロバイダのリストが、providers
オプションで定義されています。誰かが皆さんのパッケージをインストールしたら、皆さんのサービスプロバイダをこのリストに含めてもらいたいと思うことでしょう。このリストへユーザー自身がサービスプロバイダを追加することを要求する代わりに、皆さんのパッケージのcomposer.json
ファイルのextra
セクションで、プロバイダを定義してください。登録してもらいたいファサードもリストできます。
"extra": {
"laravel": {
"providers": [
"Barryvdh\\Debugbar\\ServiceProvider"
],
"aliases": {
"Debugbar": "Barryvdh\\Debugbar\\Facade"
}
}
},
ディスカバリー用にパッケージを設定したら、Laravelはサービスプロバイダとファサードをインストール時に自動的に登録します。皆さんのパッケージユーザーに、便利なインストール体験をもたらします。
パッケージディスカバリーの不使用
パッケージを利用する場合に、パッケージディスカバリーを使用したくない場合は、アプリケーションのcomposer.json
ファイルのextra
セクションに、使用しないパッケージをリストしてください。
"extra": {
"laravel": {
"dont-discover": [
"barryvdh/laravel-debugbar"
]
}
},
全パッケージに対してディスカバリーを使用しない場合は、アプリケーションのdont-discover
ディレクティブに、*
文字を指定してください。
"extra": {
"laravel": {
"dont-discover": [
"*"
]
}
},
サービスプロバイダ
サービスプロバイダは、パッケージとLaravelの間の接続ポイントです。サービスプロバイダは、Laravelのサービスコンテナと結合し、ビュー、設定、ローカリゼーションファイルなどのパッケージリソースをロードする場所をLaravelに通知する責任を担当します。
サービスプロバイダはIlluminate\Support\ServiceProvider
クラスを拡張し、register
とboot
の2メソッドを含んでいます。ベースのServiceProvider
クラスは、illuminate/support
Composerパッケージにあります。
サービスプロバイダの構造と目的について詳細を知りたければ、ドキュメントを調べてください。
リソース
設定
通常、パッケージの設定ファイルをアプリケーションのconfig
ディレクトリにリソース公開する必要があります。これにより、パッケージのユーザーはデフォルトの設定オプションを簡単に上書きできます。設定ファイルをリソース公開できるようにするには、サービスプロバイダのboot
メソッドからpublishes
メソッドを呼び出します。
/**
* 全パッケージサービスの初期起動処理
*
* @return void
*/
public function boot()
{
$this->publishes([
__DIR__.'/../config/courier.php' => config_path('courier.php'),
]);
}
これで、皆さんのパッケージのユーザーが、Laravelのvendor:publish
コマンドを実行すると、特定のリソース公開場所へファイルがコピーされます。設定がリソース公開されても、他の設定ファイルと同様に値にアクセスできます。
$value = config('courier.option');
Note: 設定ファイルでクロージャを定義しないでください。ユーザーが
config:cache
Artisanコマンドを実行すると、正しくシリアル化できません。
デフォルトパッケージ設定
独自のパッケージ設定ファイルをアプリケーションのリソース公開コピーとマージすることもできます。これにより、ユーザーは、設定ファイルのリソース公開されたコピーで実際にオーバーライドするオプションのみを定義できます。設定ファイルの値をマージするには、サービスプロバイダのregister
メソッド内でmergeConfigFrom
メソッドを使用します。
mergeConfigFrom
メソッドは、パッケージの設定ファイルへのパスを最初の引数に取り、アプリケーションの設定ファイルのコピーの名前を2番目の引数に取ります。
/**
* 全アプリケーションサービスの登録
*
* @return void
*/
public function register()
__DIR__.'/../config/courier.php', 'courier'
$this->mergeConfigFrom(
__DIR__.'/../config/courier.php', 'courier'
);
}
Note: このメソッドは設定配列の一次レベルのみマージします。パッケージのユーザーが部分的に多次元の設定配列を定義すると、マージされずに欠落するオプションが発生します。
ルート
パッケージにルートを含めている場合は、loadRoutesFrom
メソッドでロードします。このメソッドは自動的にアプリケーションのルートがキャッシュされているかを判定し、すでにキャッシュ済みの場合はロードしません。
/**
* 全パッケージサービスの初期起動
*
* @return void
*/
public function boot()
{
$this->loadRoutesFrom(__DIR__.'/../routes/web.php');
}
マイグレーション
もしパッケージがデータベースマイグレーションを含んでいる場合、loadMigrationsFrom
メソッドを使用し、Laravelへどのようにロードするのかを知らせます。loadMigrationsFrom
メソッドは引数を一つ取り、パッケージのマイグレーションのパスです。
/**
* 全パッケージサービスの初期起動
*
* @return void
*/
public function boot()
{
$this->loadMigrationsFrom(__DIR__.'/../database/migrations');
}
パッケージのマイグレーションを登録すると、php artisan migrate
コマンドが実行されるとき自動的に実行されます。マイグレーションをアプリケーションのdatabase/migrations
ディレクトリにエクスポートする必要はありません。
言語ファイル
パッケージが言語ファイルを含む場合、loadTranslationsFrom
メソッドを使用し、Laravelへどのようにロードするのかを伝えてください。たとえば、パッケージの名前がcourier
の場合、以下のコードをサービスプロバイダのboot
メソッドに追加します。
/**
* 全パッケージサービスの初期起動処理
*
* @return void
*/
public function boot()
{
$this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'courier');
}
パッケージの翻訳は、package::file.line
規約を使い参照します。ですから、courier
パッケージのmessages
ファイル中の、welcome
行をロードするには、次のようになります。
echo trans('courier::messages.welcome');
翻訳のリソース公開
パッケージの翻訳をアプリケーションのresources/lang/vendor
ディレクトリへリソース公開したい場合は、サービスプロバイダのpublishes
メソッドを使用します。publishes
メソッドはパッケージパスとリソース公開したい場所の配列を引数に取ります。たとえば、courier
パッケージの言語ファイルをリソース公開する場合は、次のようになります。
/**
* 全パッケージサービスの初期起動処理
*
* @return void
*/
public function boot()
{
$this->loadTranslationsFrom(__DIR__.'/../resources/lang', 'courier');
$this->publishes([
__DIR__.'/../resources/lang' => resource_path('lang/vendor/courier'),
]);
}
これで、皆さんのパッケージのユーザーが、Laravelのvendor:publish
Artisanコマンドを実行すると、パッケージの翻訳は指定されたリソース公開場所で公開されます。
ビュー
パッケージのビューをLaravelへ登録するには、ビューがどこにあるのかをLaravelに知らせる必要があります。そのために、サービスプロバイダのloadViewsFrom
メソッドを使用してください。loadViewsFrom
メソッドは2つの引数を取ります。ビューテンプレートへのパスと、パッケージの名前です。たとえば、パッケージ名がcourier
であれば、以下の行をサービスプロバイダのboot
メソッドに追加してください。
/**
* 全パッケージサービスの初期起動処理
*
* @return void
*/
public function boot()
{
$this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');
}
パッケージのビューは、package::view
記法を使い参照します。そのため、ビューのパスを登録し終えたあとで、courier
パッケージのdashboard
ビューをロードする場合は、次のようになります。
Route::get('admin', function () {
return view('courier::admin');
});
パッケージビューのオーバーライド
loadViewsFrom
メソッドを使用すると、Laravelはビューの2つの場所を実際に登録します。アプリケーションのresources/views/vendor
ディレクトリと指定したディレクトリです。そのため、たとえばcourier
パッケージを使用すると、Laravelは最初にカスタムバージョンのビューが開発者によってresources/views/vendor/courier
ディレクトリに配置されているかどうかを確認します。次に、ビューがカスタマイズされていない場合、LaravelはloadViewsFrom
の呼び出しで指定したパッケージビューディレクトリを検索します。これにより、パッケージユーザーはパッケージのビューを簡単にカスタマイズ/オーバーライドできます。
ビューのリソース公開
パッケージのビューをresources/views/vendor
ディレクトリでリソース公開したい場合は、サービスプロバイダのpublishes
メソッドを使ってください。publishes
メソッドはパッケージのビューパスと、リソース公開場所の配列を引数に取ります。
/**
* 全パッケージサービスの初期起動処理
*
* @return void
*/
public function boot()
{
$this->loadViewsFrom(__DIR__.'/../resources/views', 'courier');
$this->publishes([
__DIR__.'/../resources/views' => resource_path('views/vendor/courier'),
]);
}
これで皆さんのパッケージのユーザーが、Laravelのvendor::publish
Artisanコマンドを実行すると、パッケージのビューは指定されたリソース公開場所へコピーされます。
ビューコンポーネント
パッケージにビューコンポーネントが含まれている場合は、loadViewComponentsAs
メソッドを使用して、それらのロード方法をLaravelに通知します。loadViewComponentsAs
メソッドは、ビューコンポーネントのタグプレフィックスとビューコンポーネントクラス名の配列の2つの引数とります。たとえば、パッケージのプレフィックスがcourier
で、Alert
およびButton
ビューコンポーネントがある場合、サービスプロバイダのboot
メソッドへ以下を追加します。
use Courier\Components\Alert;
use Courier\Components\Button;
/**
* 全パッケージサービスの初期起動処理
*
* @return void
*/
public function boot()
{
$this->loadViewComponentsAs('courier', [
Alert::class,
Button::class,
]);
}
ビューコンポーネントをサービスプロバイダ中で登録したら、以下のようにビューの中で参照します。
<x-courier-alert />
<x-courier-button />
無名コンポーネント
パッケージが無名コンポーネントを持っている場合、"views"ディレクトリ(loadViewsFrom
で指定している場所)のcomponents
ディレクトリの中へ設置する必要があります。すると、パッケージのビュー名前空間を先頭に付けたコンポーネント名でレンダーできます。
<x-courier::alert />
コマンド
パッケージのArtisanコマンドをLaravelへ登録するには、commands
メソッドを使います。このメソッドは、コマンドクラス名の配列を引数に取ります。コマンドを登録したら、Artisan CLIを使い、実行できます。
use Courier\Console\Commands\InstallCommand;
use Courier\Console\Commands\NetworkCommand;
/**
* パッケージサービスの初期処理
*
* @return void
*/
public function boot()
{
if ($this->app->runningInConsole()) {
$this->commands([
InstallCommand::class,
NetworkCommand::class,
]);
}
}
リソース公開アセット
パッケージには、JavaScript、CSS、画像などのアセットが含まれている場合があります。これらのアセットをアプリケーションのpublic
ディレクトリにリソース公開するには、サービスプロバイダのpublishes
メソッドを使用します。この例では、関連するアセットのグループを簡単にリソース公開するために使用できるpublic
アセットグループタグも追加します。
/**
* 全パッケージサービスの初期起動
*
* @return void
*/
public function boot()
{
$this->publishes([
__DIR__.'/../public' => public_path('vendor/courier'),
], 'public');
}
これで、パッケージのユーザーがvendor:publish
コマンドを実行すると、アセットが指定するリソース公開場所にコピーされます。通常、ユーザーはパッケージが更新されるたびにアセットを上書きする必要があるため、--force
フラグを使用できます。
php artisan vendor:publish --tag=public --force
ファイルグループのリソース公開
パッケージアセットとリソースのグループを個別にリソース公開することを推奨します。たとえば、パッケージのアセットをリソース公開することを強制されることなく、ユーザーがパッケージの設定ファイルをリソース公開できるようにしたい場合もあるでしょう。パッケージのサービスプロバイダからpublishes
メソッドを呼び出すときに、それらに「タグ付け」することでこれを行うことができます。例として、パッケージのサービスプロバイダのboot
メソッドで、courier
パッケージの2公開グループ
(courier-config
とcourier-migrations
)をタグを使い定義してみましょう。
/**
* 全パッケージサービスの初期起動処理
*
* @return void
*/
public function boot()
{
$this->publishes([
__DIR__.'/../config/package.php' => config_path('package.php')
], 'courier-config');
$this->publishes([
__DIR__.'/../database/migrations/' => database_path('migrations')
], 'courier-migrations');
}
これでユーザーは、vendor::publish
Artisanコマンドを使用するときにタグ名を指定することで、グループを別々にリソース公開できます。
php artisan vendor:publish --tag=courier-config