サービスコンテナとは
たくさんのサービスを入れておく箱という認識でOK(クラスをインスタンス化してくれる箱)
箱に入れる方法
app()->bind()
で箱に登録したり
箱の中から取り出す
app()->make()
で箱の中から取り出したりをする事ができます。
実際にコードを書いた方が理解が深まると思いますので進めていきましょう。
環境
laravel8
Windows11
サービスコンテナの使い方
ルーティングの作成
最初にルーティングファイルから作ることにします。
routes > web.php
use App\Http\Controllers\LifeCycleController;
Route::get('/container', [LifeCycleController::class, 'showServiceContainer']);
web.phpに記述する事ができたらコントローラーを作成していきます。
コントローラーの作成
次にターミナルで以下を実行してコントローラーを作成していきます。
php artisan make:controller LifeCycleController
上で作成したLifeCycleControllerは以下の場所に作成されます。
app > Http > Controllers > LifeCycleController
上のコントローラーが確認できたらOKです!
サービスコンテナの中身を確認
app()
のヘルパ関数を使うと中身を確認できるので、dd()
でapp()
の中身を見てみましょう。
class LifeCycleController extends Controller
{
public function showServiceContainer()
{
dd(app());
}
}
この状態でweb.phpに記述したURLを簡易サーバーで確認すると以下のようにapp()
の中身が確認する事ができます。
上のIlluminate\Foundation\Application
の中にあるbindings:``array:71 [▶]
は、サービスコンテナに登録されているサービスの数を表しています。実際に中身を確認すると様々なサービスがあることが確認できます。
まずは簡単にサービスコンテナにサービスを登録するということをやってみます。
サービスコンテナにサービスを登録する方法
登録する方法は、
app()->bind('lifeCycle', function()
{
return 'ライフサイクルのテスト';
});
app()
ヘルパ関数にbind()
というメソッドで登録する事ができます。
登録した後に呼び出す名前を付ける必要があるので、今回はbind()
の第一引数に記述されている lifeCycle
で登録していきます。
bind()
の第二引数で実行する内容を書いていきます。今回はライフサイクルのテスト
という文字を返すという内容でやっていきます。
実際にコードを書く
上で説明したようにコントローラーに書いていきます。
app > Http > Controllers > LifeCycleController
class LifeCycleController extends Controller
{
public function showServiceContainer()
{
app()->bind('lifeCycle', function()
{
return 'ライフサイクルのテスト';
});
dd(app());
}
}
上のように書くことができたらブラウザの画面で確認してみましょう。以下のように表示されていればOK!
先ほどまでは、上のIlluminate\Foundation\Application
の中にあるbindings:``array:72 [▶]
は71
だったのですが72
に増えていることがわかります。
それでは上で追加したサービスコンテナから取り出してみましょう。
サービスコンテナから取り出す
サービスコンテナから取り出す場合は
app()->make('lifeCycle')
app()
ヘルパ関数にmake()
として引数に先ほどbind()
の第一引数で設定したlifeCycle
としてあげれば取り出す事ができます。
実際にコードを書く
上で説明したようにコントローラーに書いていきます。
app > Http > Controllers > LifeCycleController
class LifeCycleController extends Controller
{
public function showServiceContainer()
{
app()->bind('lifeCycle', function()
{
return 'ライフサイクルのテスト';
});
$test = app()->make('lifeCycle'); //追加
dd($test, app()); //ddの中に$testを追加
}
}
上のように書くことができたらブラウザの画面で確認してみましょう。以下のように表示されていればOK!
実際にbind()
で登録したライフサイクルのテスト
という文字が呼び出されているのがわかります。
依存関係の解決
サービスコンテナの中でも重要な機能として依存関係の解決という機能があります。
依存関係の解決について
依存した2つ以上のクラスを使う時に
以下のように普通のPHPであればそれぞれのクラスをnew
でインスタンス化して読み込み実行する必要があります。
$test = new Test();
$sample = new Sample($test);
$sample->run();
ですが、サービスコンテナを使用すればapp()→baind()
で紐づけてapp()→make()
で使用する際に、依存しているクラスも同時にインスタンス化してくれます。
なのでnew
でインスタンス化しなくても使用できるのです。
app()->bind('sample',Sample::class);
$sample = app()->make('sample');
$sample->run();
使い方の説明
class Sample
{
public $message;
public function __construct(Message $message)
{
$this->message = $message;
}
public function run()
{
$this->message->send();
}
}
class Message
{
public function send()
{
echo('メッセージ');
}
}
2つのクラスMessage
とSample
を作成します。
class Message
は、echo
でメッセージを表示しているだけ
class Sample
は、__construct
でMessage
クラスを読み込んでrun()
メソッドの中でMessageクラスのsend()
メソッドを設定しています。
実際にコードを書く
上で作成したコントローラー(LifeCycleController)を使用していきます。
※本来なら1ファイルに1クラスなのですが今回は分かりやすい使い方ということでLifeCycleControllerに複数のクラスを書いています。
class Message
まずはMessageクラスから書いていきます。
app > Http > Controllers > LifeCycleController
class Message
{
public function send()
{
echo('メッセージ');
}
}
class Sample
次にSampleクラスを書いていきます。
app > Http > Controllers > LifeCycleController
class Sample
{
public $message;
public function __construct(Message $message)
{
$this->message = $message;
}
public function run()
{
$this->message->send();
}
}
プロパティでpublic $message;
を書いて
インスタンス化する時にMessage
も読み込みたいので__construct(Message $message)
という書きかたで読み込みます。「これは、DIと呼ばれる仕組みで__construct()の引数にクラスを入れてあげると自動的にインスタンス化してくれます。」
$this->message
をしてあげるとMessageクラスがmessage
に入ります。
$this->message->send();
と書きMessageクラスのsend()
メソッドを使用できるようにしています。
今回はSampleクラスの方で__construct()
で初期化する時にMessageクラスも使うというようにしているのでSampleクラスを使う場合には、あらかじめMessageクラスをインスタンス化しておく必要があります。
class LifeCycleController
app > Http > Controllers > LifeCycleController
class LifeCycleController extends Controller
{
public function showServiceContainer()
{
app()->bind('lifeCycle', function()
{
return 'ライフサイクルのテスト';
});
$test = app()->make('lifeCycle');
app()->bind('sample', Sample::class); //追加
$sample = app()->make('sample'); //追加
$sample->run(); //追加
dd($test, app());
}
}
app()->bind()
で紐づける際に、呼び出す名前を引数につける必要があるので、'sample'
としておきます。今回はクラスを付けるので、Sample::class
と書くことでSampleクラスを紐づける事ができます。
続いてapp()->make('sample');
として呼び出してSampleの中にあるrun()
メソッドを表示させます。
以下のように表示されていればOKです!
出力結果
メッセージ
コントローラー全体のコード
app > Http > Controllers > LifeCycleController
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class LifeCycleController extends Controller
{
public function showServiceContainer()
{
app()->bind('lifeCycle', function()
{
return 'ライフサイクルのテスト';
});
$test = app()->make('lifeCycle');
app()->bind('sample', Sample::class); //追加
$sample = app()->make('sample'); //追加
$sample->run(); //追加
dd($test, app());
}
}
//以下すべて追加
class Sample
{
public $message;
public function __construct(Message $message)
{
$this->message = $message;
}
public function run()
{
$this->message->send();
}
}
class Message
{
public function send()
{
echo('メッセージ');
}
}
以上
上のことを理解することでLaravelに書かれているコードがかなり読みやすくなると思うので覚えておくとかなり良いと思います!