イントロダクション
サービスプロバイダーはLaravelアプリケーション全体における起動処理初期の心臓部です。皆さんのアプリケーションと同じく、Laravelのコアサービス全部もサービスプロバイダーを利用して初期起動処理を行っています。
ところで「初期起動処理」とは何を意味しているのでしょうか? サービスコンテナの結合やイベントリスナー、フィルター、それにルートなどを登録することを一般的に意味しています。サービスプロバイダーはアプリケーション設定の中心部です。
Laravelに含まれているconfig/app.php
ファイルを開けば、providers
配列が見つかるでしょう。そこにある全サービスプロバイダークラスが、アプリケーションのためにロードされます。もちろんほとんどのプロバイダーは、全てのリクエストで必ずロードされるとは限らず、そのプロバイダーが提供するサービスが必要なときにのみロードされる「遅延」プロバイダーです。
この概論ではサービスプロバイダーの書き方と、Laravelアプリケーションに登録する方法を学びます。
サービスプロバイダーの記述
全てのサービスプロバイダーは、Illuminate\Support\ServiceProvider
クラスを拡張します。この抽象クラスは皆さんのプロバイダーの中に、最低でもregister
メソッドだけは定義することを求めています。register
メソッドの中ではサービスコンテナへの登録だけを行わなくてはなりません。他のイベントリスナーやルート、その他の機能の一部でも、register
メソッドの中で登録しようとしてはいけません。
make:provider
Artisanコマンドラインにより、簡単に新しいプロバイダーが生成できます。
php artisan make:provider RiakServiceProvider
Registerメソッド
既に説明した通り、register
メソッドの中ではサービスコンテナに何かを結合することだけを行わなければなりません。イベントリスナーやルート、その他のどんな作業もregister
メソッドの中では決して行ってはいけません。これを守らないと、サービスプロバイダーがまだロードしていないサービスを意図せず使ってしまう羽目になるでしょう。
では、基本的なプロバイダーを見てみましょう。
<?php
namespace App\Providers;
use Riak\Connection;
use Illuminate\Support\ServiceProvider;
class RiakServiceProvider extends ServiceProvider
{
/**
* コンテナへの結合登録
*
* @return void
*/
public function register()
{
$this->app->singleton('Riak\Contracts\Connection', function ($app) {
return new Connection(config('riak'));
});
}
}
このサービスプロバイダーではregister
メソッドだけが定義されています。そして、サービスコンテナにRiak\Contracts\Connection
の実装を定義しています。サービスコンテナがどのように動作するのかまだ理解できていなければ、ドキュメントを調べてください。
Bootメソッド
ではイベントリスナーをサービスプロバイダーで登録する必要がある場合は、どうすればよいのでしょうか? boot
メソッドの中で行ってください。このメソッドは、他の全サービスプロバイダーが登録し終えてから呼び出されます。つまりフレームワークにより登録された、他のサービス全てにアクセスできるのです。
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* サービス起動の登録後に、実行される
*
* @return void
*/
public function boot()
{
view()->composer('view', function () {
//
});
}
/**
* コンテナへの結合登録
*
* @return void
*/
public function register()
{
//
}
}
bootメソッドの依存注入
boot
メソッドでは依存をタイプヒントにより指定可能です。サービスコンテナは必要な依存を自動的に注入してくれます。
use Illuminate\Contracts\Routing\ResponseFactory;
public function boot(ResponseFactory $factory)
{
$factory->macro('caps', function ($value) {
//
});
}
プロバイダーの登録
全てのサービスプロバイダーは、config/app.php
設定ファイルで登録されています。このファイルには起動するサービスプロバイダーの名前をリストしてあるproviders
配列が含まれています。この配列にはデフォルトとして、コアのサービスプロバイダーが登録されています。これらのプロバイダーは、メール送信、キュー、キャッシュなどのLaravelコアコンポーネントの初期起動を行っています。
プロバイダーを登録するには、この配列に追加するだけです。
'providers' => [
// その他のサービスプロバイダー
App\Providers\AppServiceProvider::class,
],
遅延プロバイダー
もし皆さんのプロバイダーが、サービスコンテナへコンテナ結合を登録するだけであるなら、その結合が実際に必要になるまで登録を遅らせる方が良いでしょう。こうしたプロバイダーのローディングを遅らせるのは、リクエストがあるたびにファイルシステムからロードされなくなるため、アプリケーションのパフォーマンスを向上させます。
プロバイダーを遅延ロードするには、defer
プロパティーにtrue
をセットし、provides
メソッドを定義します。provides
メソッドはそのプロバイダーで登録するサービスコンテナ結合名を返します。
<?php
namespace App\Providers;
use Riak\Connection;
use Illuminate\Support\ServiceProvider;
class RiakServiceProvider extends ServiceProvider
{
/**
* プロバイダーのローディングを遅延させるフラグ
*
* @var bool
*/
protected $defer = true;
/**
* サービスプロバーダーの登録
*
* @return void
*/
public function register()
{
$this->app->singleton('Riak\Contracts\Connection', function ($app) {
return new Connection($app['config']['riak']);
});
}
/**
* このプロバイダーにより提供されるサービス
*
* @return array
*/
public function provides()
{
return ['Riak\Contracts\Connection'];
}
}
Laravelは遅延サービスプロバイダーが提示した全サービスのリストをコンパイルし、サービスプロバイダーのクラス名と共に保存します。その後、登録されているサービスのどれか一つを依存解決する必要が起きた時のみ、Laravelはそのサービスプロバイダーをロードします。