目次
DIとサービスコンテナについて
Laravelでは、様々な機能をコントローラーに手軽に取り込み、利用をすることができます。ただ、この機能は普通はあり得ないことでしょう。「必要なクラスのインスタンスが自動的に引数として用意される機能」が実現されているのは、Laravelに標準実装されている「サービスコンテナ」という機能のおかげとなります。
サービスコンテナとは
サービスコンテナは、あるクラスと依存関係にあるクラスのインスタンスを管理する機能を提供することとなります。
コントローラーのコンストラクタやアクションメソッドに引数が用意されている場合、サービスコンテナはその引数に設定されたクラスのインスタンスを必要に応じて渡します。
新たにインスタンスを用意する場合もあれば、実際にインスタンスが用意されている場合、探して渡す場合もあります。
このような機能を依存性注入と呼びます。英語ではDependency Injection 略してDIと呼びます。
上記に伴い、サービスコンテナとは、Laravelに用意されているDI機能を実装したクラスということが分かりますね。
サービスコンテナの基本的な使い方
では、サービスコンテナを実際に使用してみましょう。
まずは簡単なクラスを用意します。
「app」フォルダの中に「TestClasses」というフォルダを作成し、その中に「TestService.php」というファイルを作成・以下のコードを記述してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php namespace App\TestClasses; class TestService { private $strMsg; private $aryData; public function __construct() { $this->strMsg = 'これはTestserviceです。'; $this->aryData = ['one', 'two', 'three']; } public function say() { return $this->strMsg; } public function data() { return $this->aryData; } } |
2つのプロパティとコンストラクタ・各プロパティを返却するメソッドからなる簡単なクラスです。
アクションから TestService を利用
では、HelloControllerを/app/Http/Controller/へ作成し、以下の様に記述してください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<?php namespace App\Http\Controllers; use App\TestClasses\TestService; class HelloController extends Controller { public function index(TestService $testservice) { $data = [ 'strMsg' => $testservice->say(), 'aryData' => $testservice->data() ]; return view('hello.index', $data); } } |
/helloへアクセスした際にindexアクションが実行されるようにルート情報にindexアクションメソッドを/helloに割り当てておきましょう。
1 2 3 |
use App\Http\Controllers\HelloController; Route::get('/hello', 'App\Http\Controllers\HelloController@index')->name('hello'); |
また、/resources/views/hello/index.blade.phpをテンプレートとして用意してください。
以下、bodyのみ記載致します。
1 2 3 4 5 6 7 8 9 10 11 |
<body> <h1>Hello</h1> <p>{!!$strMsg!!}</p> <ul> @foreach($aryData as $item) <li> {!!$item!!} </li> @endforeach </ul> </body> |
/helloにアクセスしてみてください。
下記の様に表示されていたら、無事サービスコンテナを使用することができていると思います。
TestServiceからsay()・data()メソッドを取得した結果をテンプレート側にそのまま表示しています。
HelloController@indexで引数$testserviceに、testserviceクラスのインスタンスが渡され、メソッドをそこから呼び出し、値を取り出しているということですね。
このようにメソッドの引数にクラスを指定するだけでインスタンスが使用できるようになる機能を「メソッドインジェクション」と呼びます。
インスタンスを明示的に生成
上記で説明した依存性注入では、「引数をただ用意しただけ」で自動的にインスタンスを生成し、値を渡します。
しかし、引数を使用せずにメソッド内で必要なインスタンスを取得したい場合もあります。
app関数
laravelに標準実装されているappというヘルパ関数があります。これは引数なしのシンプルな関数です。このapp関数は引数を使用せずにサービスコンテナのインスタンスを返します。
1 |
$変数 = app(クラス名); //指定したクラスのインスタンスを取得 |
また、app関数で取得したサービスコンテナから「make」メソッドで呼び出すことでインスタンスを取得することも可能です。こちらも引数にクラス名を記述します。
1 |
$変数 = app()->make(クラス名); //指定したクラスのインスタンスを取得 |
resolve関数
このほか、サービスコンテナから依存性を解決するインスタンスを取得する専用関数としてresolve関数も用意されています。
1 |
$変数 = resolve(クラス名); //指定したクラスのインスタンスを取得 |
これらを使用することで、引数を使用せずに必要な場面で明示的にインスタンスを取得することができます。