イントロダクション
パッケージは、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');
Warning!! 設定ファイルでクロージャを定義しないでください。ユーザーが
config:cache
Artisanコマンドを実行すると、正しくシリアル化できません。
デフォルトパッケージ設定
独自のパッケージ設定ファイルをアプリケーションのリソース公開コピーとマージすることもできます。これにより、ユーザーは、設定ファイルのリソース公開されたコピーで実際にオーバーライドするオプションのみを定義できます。設定ファイルの値をマージするには、サービスプロバイダのregister
メソッド内でmergeConfigFrom
メソッドを使用します。
mergeConfigFrom
メソッドは、パッケージの設定ファイルへのパスを最初の引数に取り、アプリケーションの設定ファイルのコピーの名前を2番目の引数に取ります。
/**
* 全アプリケーションサービスの登録
*
* @return void
*/
public function register()
{
$this->mergeConfigFrom(
__DIR__.'/../config/courier.php', 'courier'
);
}
Warning!! このメソッドは設定配列の一次レベルのみマージします。パッケージのユーザーが部分的に多次元の設定配列を定義すると、マージされずに欠落するオプションが発生します。
ルート
パッケージにルートを含めている場合は、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__.'/../lang', 'courier');
}
パッケージの翻訳は、package::file.line
規約を使い参照します。ですから、courier
パッケージのmessages
ファイル中の、welcome
行をロードするには、次のようになります。
echo trans('courier::messages.welcome');
翻訳のリソース公開
もし、パッケージの翻訳をアプリケーションのlang/vendor
ディレクトリにリソース公開したい場合は、サービスプロバイダのpublishes
メソッドを使用することができます。publishes
メソッドには、パッケージのパスと公開したい場所を配列で指定します。例えば、courier
パッケージの翻訳ファイルを公開するには、以下のようにします。
/**
* 全パッケージサービスの初期起動処理
*
* @return void
*/
public function boot()
{
$this->loadTranslationsFrom(__DIR__.'/../lang', 'courier');
$this->publishes([
__DIR__.'/../lang' => $this->app->langPath('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('/dashboard', function () {
return view('courier::dashboard');
});
パッケージビューのオーバーライド
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コマンドを実行すると、パッケージのビューは指定されたリソース公開場所へコピーされます。
ビューコンポーネント
Bladeコンポーネントを利用するパッケージを構築する場合、またはコンポーネントを従来と異なるディレクトリへ配置する場合、コンポーネントクラスとそのHTMLタグエイリアスを手作業で登録し、Laravelがコンポーネントを見つける場所を認識できるようにする必要があります。通常、パッケージのサービスプロバイダのboot
メソッドで、コンポーネントを登録する必要があります。
use Illuminate\Support\Facades\Blade;
use VendorPackage\View\Components\AlertComponent;
/**
* アプリケーションの全サービスの初期起動処理
*
* @return void
*/
public function boot()
{
Blade::component('package-alert', AlertComponent::class);
}
コンポーネントを登録したら、タグエイリアスを使いレンダリングします。
<x-package-alert/>
パッケージコンポーネントの自動ロード
もしくは、componentNamespace
メソッドを使用して、コンポーネントクラスを規約に従いオートロードできます。例えば、Nightshade
パッケージにCalendar
とColorPicker
コンポーネントがあり、これらがNightshade\Views\Components
名前空間内に存在しているとしましょう。
use Illuminate\Support\Facades\Blade;
/**
* パッケージの全サービスの初期起動処理
*
* @return void
*/
public function boot()
{
Blade::componentNamespace('Nightshade\Views\Components', 'nightshade');
}
これにより、パッケージ名::
記法を使用し、ベンダーの名前空間により、パッケージコンポーネントが利用できるようになります。
<x-nightshade::calendar />
<x-nightshade::color-picker />
Bladeは、コンポーネント名をパスカルケース化し、このコンポーネントとリンクしているクラスを自動的に検出します。サブディレクトリも「ドット」記法でサポートしています。
無名コンポーネント
パッケージが無名コンポーネントを持っている場合、"views"ディレクトリ(loadViewsFrom
で指定している場所)のcomponents
ディレクトリの中へ設置する必要があります。すると、パッケージのビュー名前空間を先頭に付けたコンポーネント名でレンダできます。
<x-courier::alert />
"About" Artisanコマンド
Laravelの組み込みabout
Artisanコマンドは、アプリケーションの環境と設定の概要を表示します。パッケージではAboutCommand
クラスを使用して、このコマンドの出力に追加情報を追加できます。一般的に、この情報はパッケージサービスプロバイダのboot
メソッドに追加します。
use Illuminate\Foundation\Console\AboutCommand;
/**
* アプリケーションの全サービスの初期起動処理
*
* @return void
*/
public function boot()
{
AboutCommand::add('My Package', fn () => ['Version' => '1.0.0']);
}
コマンド
パッケージの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