パッケージ開発
イントロダクション
パッケージはLaravelに機能を追加する一番重要な方法です。パッケージとして何でも動作させることができます。たとえば日付ライブラリーであるCarbonや、振る舞い駆動開発(BDD)テストフレームワークのBehatなどです。
もちろんパッケージには、色々な種類が存在しています。スタンドアローンで動作するパッケージがあります。つまり、どんなPHPフレームワークでも動作します。CarbonもBehatもスタンドアローンパッケージの例です。Laravelと一緒に使用するにはcomposer.json
ファイルでただ使用を指定するだけです。
逆にLaravelと一緒に使用することを意図したパッケージもあります。こうしたパッケージはLaravelアプリケーションを高めることを特に意図したルート、コントローラー、ビュー、設定を持つことでしょう。このガイドはLaravelに特化したパッケージの開発を主に説明します。
ファサード使用の注意
Laravelアプリケーションをプログラムする場合は、契約とファサードのどちらを使用しても、一般的には問題ありません。両方共に基本的に同じレベルのテスタビリティがあるからです。しかし、パッケージを書く場合は、ファサードの代わりに、契約を使用してください。パッケージでは、Laravelのテストヘルパの全てへアクセスができないためです。ファサードをモックするよりは、契約をモックしたり、スタブするほうが簡単です。
サービスプロバイダ
サービスプロバイダはパッケージとLaravelを結びつけるところです。サービスプロバイダは何かをLaravelのサービスコンテナと結合し、ビューや設定、言語ファイルのようなリソースをどこからロードするかをLaravelに知らせる責務を持っています。
サービスプロバイダはIlluminate\Support\ServiceProvider
クラスを拡張し、register
とboot
の2メソッドを含んでいます。ベースのServiceProvider
クラスは、illuminate/support
Composerパッケージにあります。
サービスプロバイダの構造と目的について詳細を知りたければ、ドキュメントを調べてください。
ルーティング
パッケージのルートを定義するには、パッケージのサービスプロバイダのboot
メソッドからルートファイルをrequire
するだけです。ルートファイルの中から、典型的なLaravelアプリケーションと同様に、Illuminate\Support\Facades\Route
ファサードを使い、ルートを登録します。
/**
* サービス初期処理登録後の処理
*
* @return void
*/
public function boot()
{
if (! $this->app->routesAreCached()) {
require __DIR__.'/../../routes.php';
}
}
リソース
設定
通常、パッケージの設定ファイルをアプリケーション自身のconfig
ディレクトリへ公開する必要が起きます。これにより、ユーザが皆さんのパッケージのデフォルト設定オプションを簡単にオーバーライドできるようになります。設定ファイルを公開するには、サービスプロバイダのboot
メソッドで、publishes
メソッドを呼び出してください。
/**
* サービス初期処理登録後の処理
*
* @return void
*/
public function boot()
{
$this->publishes([
__DIR__.'/path/to/config/courier.php' => config_path('courier.php'),
]);
}
これで、皆さんのパッケージのユーザが、Laravelのvendor:publish
コマンドを実行すると、特定の公開場所へファイルがコピーされます。もちろん、設定が公開されても、他の設定ファイルと同様に値にアクセスできます。
$value = config('courier.option');
デフォルトパッケージ設定
もしくは、アプリケーションへ公開したコピーと、自身のパッケージの設定ファイルをマージすることもできます。これにより、ユーザは公開された設定のコピーの中で、実際にオーバーライドしたいオプションのみを定義すればよくなります。設定をマージする場合は、サービスプロバイダのregister
メソッドの中で、mergeConfigFrom
メソッドを使用します。(訳注:registerではなく、bootメソッドの間違いかもしれません)
/**
* コンテナ結合の登録
*
* @return void
*/
public function register()
{
$this->mergeConfigFrom(
__DIR__.'/path/to/config/courier.php', 'courier'
);
}
マイグレーション
もしパッケージがデータベースマイグレーションを含んでいる場合、loadMigrationsFrom
メソッドを使用し、Laravelへどのようにロードするのかを知らせます。loadMigrationsFrom
メソッドは引数を一つ取り、パッケージのマイグレーションのパスです。
/**
* サービス初期処理登録後の処理
*
* @return void
*/
public function boot()
{
$this->loadMigrationsFrom(__DIR__.'/path/to/migrations');
}
パッケージのマイグレーションが登録されると、php artisan migrate
コマンド実行時に、自動的にパッケージのマイグレーションも行われます。アプリケーションのdatabase/migrations
ディレクトリへ公開する必要はありません。
言語ファイル
パッケージが言語ファイルを含む場合、loadTranslationsFrom
メソッドを使用し、Laravelへどのようにロードするのかを伝えてください。たとえば、パッケージの名前がcourier
の場合、以下のコードをサービスプロバイダのboot
メソッドに追加します。
/**
* サービス初期処理登録後の処理
*
* @return void
*/
public function boot()
{
$this->loadTranslationsFrom(__DIR__.'/path/to/translations', '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__.'/path/to/translations', 'courier');
$this->publishes([
__DIR__.'/path/to/translations' => resource_path('lang/vendor/courier'),
]);
}
これで、皆さんのパッケージのユーザが、Laravelのvendor:publish
Artisanコマンドを実行すると、パッケージの翻訳は指定された公開場所で公開されます。
ビュー
パッケージのビューをLaravelへ登録するには、ビューがどこにあるのかをLaravelに知らせる必要があります。そのために、サービスプロバイダのloadViewsFrom
メソッドを使用してください。loadViewsFrom
メソッドは2つの引数を取ります。ビューテンプレートへのパスと、パッケージの名前です。たとえば、パッケージ名がcourier
であれば、以下の行をサービスプロバイダのboot
メソッドに追加してください。
/**
* サービス初期処理登録後の処理
*
* @return void
*/
public function boot()
{
$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
}
パッケージのビューは、package::view
記法を使い参照します。そのため、ビューのパスを登録し終えたあとで、courier
パッケージのadmin
ビューをロードする場合は、次のようになります。
Route::get('admin', function () {
return view('courier::admin');
});
パッケージビューのオーバーライド
loadViewsFrom
メソッドを使用する場合、Laravelはビューの2つの場所を実際には登録します。一つはアプリケーションのresources/views/vendor
ディレクトリで、もう一つは皆さんが指定したディレクトリです。では、courier
の例を使って確認しましょう。Laravelは最初にresources/views/vendor/courier
の中に、カスタムバージョンのビューが開発者により用意されていないかチェックします。カスタムビューが用意されていなければ、次にloadViewsFrom
の呼び出しで指定した、パッケージビューディレクトリを探します。この仕組みのおかげで、パッケージのビューがエンドユーザにより簡単にカスタマイズ/オーバーライドできるようになっています。
ビューの公開
パッケージのビューをresources/views/vendor
ディレクトリで公開したい場合は、サービスプロバイダのpublishes
メソッドを使ってください。publishes
メソッドはパッケージのビューパスと、公開場所の配列を引数に取ります。
/**
* サービス初期処理登録後の処理
*
* @return void
*/
public function boot()
{
$this->loadViewsFrom(__DIR__.'/path/to/views', 'courier');
$this->publishes([
__DIR__.'/path/to/views' => resource_path('views/vendor/courier'),
]);
}
これで皆さんのパッケージのユーザが、Laravelのvendor::publish
Artisanコマンドを実行すると、パッケージのビューは指定された公開場所へコピーされます。
コマンド
パッケージのArtisanコマンドをLaravelへ登録するには、commands
メソッドを使います。このメソッドは、コマンドクラス名の配列を引数に取ります。コマンドを登録したら、Artisan CLIを使い、実行できます。
/**
* アプリケーションサービスの初期処理
*
* @return void
*/
public function boot()
{
if ($this->app->runningInConsole()) {
$this->commands([
FooCommand::class,
BarCommand::class,
]);
}
}
公開アセット
パッケージにはJavaScriptやCSS、画像などのアセットを含むと思います。こうしたアセットをpublic
ディレクトリへ公開するには、サービスプロバイダのpublishes
メソッドを使用してください。次の例では、関連するアセットをまとめて公開するためにpublic
アセットグループタグも追加指定しています。
/**
* サービス初期処理登録後の処理
*
* @return void
*/
public function boot()
{
$this->publishes([
__DIR__.'/path/to/assets' => public_path('vendor/courier'),
], 'public');
}
これで、皆さんのパッケージのユーザが、vendor:publish
コマンドを実行した時に、アセットは指定した公開場所へコピーされます。通常、パッケージが更新されるごとに、アセットをオーバーライトする必要がありますので、--force
フラッグと一緒に使用します。
php artisan vendor:publish --tag=public --force
ファイルグループの公開
アセットとリソースのパッケージグループを別々に公開したいこともあるでしょう。たとえば、パッケージのアセットの公開を強要せずに、設定ファイルを公開したい場合です。パッケージのサービスプロバイダーで呼び出す、publishes
メソッド実行時の「タグ指定」で行えます。例として、パッケージのサービスプロバイダのboot
メソッドで、2つの公開グループを定義してみましょう。
/**
* サービス初期処理登録後の処理
*
* @return void
*/
public function boot()
{
$this->publishes([
__DIR__.'/../config/package.php' => config_path('package.php')
], 'config');
$this->publishes([
__DIR__.'/../database/migrations/' => database_path('migrations')
], 'migrations');
}
これでユーザは、vendor::publish
Artisanコマンドを使用するときにタグ名を指定することで、グループを別々に公開できます。
php artisan vendor:publish --tag=config