前回はサービスプロバイダーの仕組みを既存のコードを追って理解しました。今回は自分でサービスプロバイダーを作成して、その中でサービスコンテナへサービスを登録してみます。
サービスの作成
まずは、簡単なサービスを作成します。
app/Servicesディレクトリに Messengerディレクトリを作成し、Messengerサービスと位置付けます。Messengerインターフェースと、その実装である MailMessenger, BikeMessengerクラスを作成します。
<?php // app/Services/Messenger/Messenger.php namespace App\Services\Messenger; interface Messenger { public function send($message); }
<?php // app/Services/Messenger/MailMessenger.php namespace App\Services\Messenger; class MailMessenger implements Messenger { public function send($message) { // ここで、メールでメッセージを送る return "メールで $message を送りました。"; } }
<?php // app/Services/Messenger/BikeMessenger.php namespace App\Services\Messenger; class BikeMessenger implements Messenger { public function send($message) { // ここで、バイクに乗ってメッセージを届ける return "バイク便で $message を届けました。"; } }
ルーティング
Messengerを使用する、ルート設定を行います。
// app/Http/routes.php use App\Services\Messenger\Messenger; Route::get('send_message/{message}', function(Messenger $messenger, $message){ return $messenger->send($message); });
ここでは、コントローラを作成せずに、クロージャーを使ってアクションを定義します。オプションパラメータ $messge を受け取り、それをMessengerサービスに渡し、戻り値を画面に表示しています。
クロージャーでは、タイプヒントで依存注入を行い、Messengerインターフェースのインスタンスを受け取ります。
この時点で、 http://localhost:8000/send_message/SOME_MESSAGE にアクセスすると。Laravelは、Mesengerインターフェースに対して、どのクラスのインスタンスを生成してよいか分からない為、以下のようにエラーとなります。
Target [App\Services\Messenger\Messenger] is not instantiable.
AppServiceProvider
自分でサービスプロバイダーを作成する前に、まずは、AppServiceProviderを使ってみます。
Laravelでは、アプリケーション固有の初期処理を実装する場所として、app/Providers/AppServiceProvider.php があります。この中で、今回作成した Messengerサービスをコンテナへ登録してみます。
<?php // app/Providers/AppServiceProvider.php namespace App\Providers; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot() { // } public function register() { $this->app->bind( 'Illuminate\Contracts\Auth\Registrar', 'App\Services\Registrar' ); // Messengerサービスのバインド $this->app->bind( // ① 追加 'App\Services\Messenger\Messenger', 'App\Services\Messenger\MailMessenger' // メール便 ); // $this->app->bind( // ② 追加 // 'App\Services\Messenger\Messenger', // 'App\Services\Messenger\BikeMessenger' // バイク便 // ); } }
① Messengerインターフェースに対して、MailMessengerクラスをインスタンスを生成するよう支持しています。
② BikeMessengerに切り替えたい場合は、こちらを使います。
この時点で、 http://localhost:8000/send_message/重要書類 にアクセスすると、下記のように表示されます。
メールで 重要書類 を送りました。
②のBikeMessengerに切り替えて http://localhost:8000/send_message/重要書類 にアクセスすると、以下のように表示されます。
バイク便で 重要書類 を届けました。
次に自分でサービスプロバイダーを作成したいと思います。
先ほどのAppServiceProvider内の①②のコードは、ここで削除してください。
サービスプロバイダーの作成
サービスプロバイダーは artisan コマンドで作成します。
php artisan make:provider MessengerProvider
app/Providers/MessengerProvider.php が作成されました。
AppServiceProviderの時と同様に、Messengerサービスをコンテナへバインドするコードを追加します。
<?php // app/Providers/MessengerServiceProvider.php namespace App\Providers; use Illuminate\Support\ServiceProvider; class MessengerServiceProvider extends ServiceProvider { public function boot() { // } public function register() { // Messengerサービスのバインド $this->app->bind( // ① 追加 'App\Services\Messenger\Messenger', 'App\Services\Messenger\MailMessenger' // メール便 ); // $this->app->bind( // ② 追加 // 'App\Services\Messenger\Messenger', // 'App\Services\Messenger\BikeMessenger' // バイク便 // ); } }
次に、Laravelが起動処理の中で MessengerServiceProviderをコールするように、config/app.php に MessengerServiceProviderを追加します。
<?php // config/app.php // … return [ 'providers' => [ // ... /* * Application Service Providers... */ App\Providers\AppServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, App\Providers\MessengerProvider::class, // 追加 // ... ], // ... ];
ここで、 http://localhost:8000/send_message/重要書類 にアクセスすると、下記のように表示されます。
メールで 重要書類 を送りました。
まとめ
- サービスコンテナのバインディングはサービスプロバイダーで行う。
- アプリケーション固有のサービスプロバイダーは AppServiceProvider.php。
- サービスプロバイダーは artisan make:provider コマンドで作成する。