イントロダクション
サービスプロバイダーは、Laravelアプリケーション全体の初期起動処理の心臓部です。皆さんのアプリケーションと同様に、Laravelの全コアサービスも、サービスプロバイダーを通じて初期起動処理を行っています。
ところで、「初期起動処理」とは何を意味しているのでしょうか?サービスコンテナの結合やイベントリスナー、フィルター、それにルートなどを登録することを一般的に意味しています。サービスプロバイダーは、アプリケーション設定の中心部です。
Laravelに含まれているconfig/app.php
ファイルを開けば、providers
配列が見つかるでしょう。そこにある全サービスプロバイダークラスが、アプリケーションのためにロードされます。もちろん、ほとんどのプロバイダーは、全てのリクエストで必ずロードされるとは限らず、そのプロバイダーが提供するサービスが必要なときにのみロードされる、「遅延」プロバイダーです。
この概論では、サービスプロバイダーの書き方と、Laravelアプリケーションに登録する方法を学びます。
プロバイダーの基本サンプル
全てのサービスプロバイダーは、Illuminate\Support\ServiceProvider
クラスを拡張します。この抽象クラスは皆さんのプロバイダーの中に、最低でもregister
メソッドだけ定義することを求めています。register
メソッドの中では、サービスコンテナへの登録だけを行わなくてはなりません。他のイベントリスナーやルート、その他の機能の一部でも、register
メソッドの中で登録しようとしてはいけません。
make:provider
Artisanコマンドラインにより、簡単に新しいプロバイダーが生成できます。
php artisan make:provider RiakServiceProvider
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($app['config']['riak']);
});
}
}
このサービスプロバイダーでは、register
メソッドだけが定義されています。そして、サービスコンテナにRiak\Contracts\Connection
の実装を定義しています。サービスコンテナがどのように動作するのか理解できなくても、心配ありません。すぐに学習することになります。
このクラスは、App\Providers
の名前空間にあります。Laravelのデフォルトのサービスプロバイダー設置場所だからです。しかし、ご希望であれば変更可能です。サービスプロバイダーは、Composerがオートロード可能であれば、どこにでも自由に配置できます。
bootメソッド
では、イベントリスナーをサービスプロバイダーで登録する必要がある場合は、どうすればよいのでしょうか?boot
メソッドの中で行ってください。このメソッドは、他の全サービスプロバイダーが登録し終えてから呼び出されます。つまり、フレームワークにより登録された、他のサービス全部にアクセスできるのです。
<?php namespace App\Providers;
use Event;
use Illuminate\Support\ServiceProvider;
class EventServiceProvider extends ServiceProvider {
/**
* サービス起動の登録後に、実行される
*
* @return void
*/
public function boot()
{
Event::listen('SomeEvent', 'SomeEventHandler');
}
/**
* コンテナへの結合を登録する
*
* @return void
*/
public function register()
{
//
}
}
boot
メソッドでは、依存をタイプヒントにより指定可能です。サービスコンテナは必要な依存を自動的に注入してくれます。
use Illuminate\Contracts\Events\Dispatcher;
public function boot(Dispatcher $events)
{
$events->listen('SomeEvent', 'SomeEventHandler');
}
プロバイダーの登録
全てのサービスプロバイダーは、config/app.php
設定ファイルで登録されています。このファイルには、サービスプロバイダーの名前をリストし、登録することができるproviders
配列が含まれています。この配列にはデフォルトで、コアのサービスプロバイダーが登録されています。こうしたプロバイダーは、メール送信、キュー、キャッシュなどのLaravelコアコンポーネントの初期起動を行っています。
プロバイダーに登録するには、この配列に追加するだけです。
'providers' => [
// 他のサービスプロバイダー
'App\Providers\AppServiceProvider',
],
遅延プロバイダー
もし皆さんのプロバイダーが、サービスコンテナへ結合を登録するだけでしたら、登録する結合が実際に必要になるまで、登録を遅らせる方が良いでしょう。こうしたプロバイダーのローディングを遅らせるのは、リクエストがあるたびにファイルシステムからロードされなくなるため、アプリケーションのパフォーマンスを向上させます。
プロバイダーを遅延ロードするには、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はそのサービスプロバイダーをロードします。