🍣

【学習メモ】Laravelのサービスコンテナについて調べたこと

2021/04/07に公開

Laravelにはサービスコンテナ、サービスプロバイダという仕組みがあります。
これらについて全くの無知だったため、調べました。

・サービスコンテナとは?
【Laravel】サービスコンテナとは?2つの強力な武器を持ったインスタンス化マシーン。簡単に解説。
上記のサイトによると、サービスコンテナとは
「クラスをインスタンス化してくれる便利な機能」のようです。

$ClassA = app()->make(ClassA::class);

のようにして使います。
こうすると変数$ClassAにClassAのインスタンスが代入されます。

・では、何が便利なのか?
一つは「依存解決をしてくれる」こと
もう一つは「インスタンス化の方法を選べる」こと
のようです。

・依存解決をしてくれると何がいいのか?
ここにインスタンス化したいClassAがあるとします。このClassAはコンストラクタの中でClassBをインスタンス化して利用しているとします。するとClassAをインスタンス化するためには、まず最初にClassBをインスタンス化し、それを引数にしてClassAをインスタンス化しなければなりません。

サービスコンテナを使うと、ClassAをインスタンス化する際に、これ(ClassBのインスタンス化)を自動的にやってくれます。

流れとしては、

サービスコンテナ経由でClassAのインスタンス化を宣言
サービスコンテナがClassAを検査し、ClassAの内部でClassBが使われていることを発見
サービスコンテナがClassBをインスタンス化
インスタンス化したClassBを引き渡し、ClassAをインスタンス化

とイメージしました。
また、ClassBがさらにClassCをインスタンス化して使っていても、そのClassCがさらにClassDがインスタンス化して使っていたとしても、サービスコンテナは全てをインスタンス化して順繰りに渡していき、最終的なClassAのインスタンス化を終了させてくれます。

・インスタンス化の方法を選べるとはどういうことか?
ClassEをインスタンス化する際に、ClassEが持つプロパティ$hogeに文字列'hogehoge'を代入したいとします。

class ClassE
{
    public $hoge;

    public function __construct()
    {
    }
}

$app->bindという機能を使うことでそれができます。
$app->bindは、第一引数に「インスタンス化方法をカスタマイズしたいクラス」を、第二引数に「インスタンス化方法」を記述します。
例えば、


app()->bind(ClassE::class, function () {
    $classE = new ClassE();
    $classE->hoge = 'hogehoge';
    return $classE;
});

とした場合、

$ClassE = $app()->make(ClassE::class);

を実行すると、サービスコンテナは
$classE = new ClassE();
$classE->hoge = 'hogehoge';
を実行した後で、
return $classE;
によってClassEのインスタンスを返します。

ClassEに依存解決をする必要があるのならば、


app()->bind(ClassE::class, function ($app) {
-    $classE = new ClassE();
+    $classE = $app()->make(ClassE::class);
    $classE->hoge = 'hogehoge';
    return $classE;
});

と、bind内で$app()->make()を使います。


app()->bind(ClassE::class, function ($app) {
    $classX = $app()->make(ClassX::class);
    return $classX;
});

と記述すれば、$app()->make(ClassE::class);の返り値はClassXのインスタンスになります。

このbindによるインスタンス化方法の記述を「結合」と言います。

Discussion