のぐそんブログ

暗いおじさんがシコシコ書くブログです。

Laravelのサービスコンテナメモ(自分用)

サービスコンテナがよくわからないので自分用のメモです。
この記事は、自分用の備忘録として記載しているので、見てもよくわからないと思います。

サービスコンテナ

サービスコンテナとは...

Laravelのサービスコンテナは、クラス間の依存を管理する強力な管理ツールです。依存注入というおかしな言葉は主に「コンストラクターか、ある場合にはセッターメソッドを利用し、あるクラスをそれらに依存しているクラスへ外部から注入する」という意味で使われます。
https://readouble.com/laravel/5.7/ja/container.html

難しいです。。。
よくわからないのですが、サービスコンテナにインスタンスの生成方法を登録」 したり、インスタンスを生成して返却したりする機能のようです。

サービスコンテナの中身

まずは、サービスコンテナはどこにいるかというとapp()を確認するとbindingsに入っています。

サービスコンテナに追加する

サービスコンテナに追加する為にはbindメソッドを利用します。
※他にもsingletonや、bindIfなどなど他のメソッドもあります。

//  クロージャの第2引数はインスタンス生成時に渡すパラメーターを設定することができます
app()->bind('ServiceContainerName',function(Application $app, array $params){
    return new ServiceContainerName($params[0])
})

サービスコンテナからサービスを取り出す

取り出しかたは色々ありますがapp->make(サービス名)で取り出せます。

$service = app()->make('ServiceContainerName',['hogehoge');

サービスコンテナで依存関係を解決する

以下のような2つのClassがあるとする。

  • SampleClass
  • SubClass
namespace App\Http;

class SampleClass
{
    public $slack;

    public function __construct(SubClass $subClass){

        $this->subClass = $subClass;

    }

    public function run(){

        $this->subClass->hoge();

    }
}
<?php

namespace App\Http;

class SubClass
{
    public function hoge(){

        dd('ほげほげ');

    }
}

サービスコンテナを利用しない場合

当たり前だが、SampleClassで利用しているSubClassを引数として渡す必要がある。

    $sampleClass = new \App\Http\SampleClass(new \App\Http\SubClass());
    $sampleClass ->run(); // ほげほげ

サービスコンテナを利用する場合

なんとSubClassを連携する必要がない。
サービスコンテナが依存関係を解決してくれる。

    app()->bind('sampleClass',\App\Http\SampleClass::class);
    $sampleClass = app()->make('sampleClass');
    $sampleClass ->run(); // ほげほげ

以下のように明確にインスタンスの生成処理を定義することもできます。

    app()->bind(\App\Http\SampleClass::class,function(){
       $subClass = new \App\Http\SubClass();
       return new \App\Http\SampleClass($subClass);
    });
    
    $sampleClass = app()->make(\App\Http\SampleClass::class);
    $sampleClass ->run(); // ほげほげ

インターフェイスをサービスコンテナに登録

以下の1つのインターフェイスと、クラスを用意します。

  • AnimalIf
  • DogClass
  • CatClass
<?php

namespace App\Http;

interface AnimalIf
{
    public function bark();
}
<?php

namespace App\Http;

class DogClass implements AnimalIf
{
    public function bark()
    {
        dd('わんわん');
    }
}
<?php

namespace App\Http;

class CatClass implements AnimalIf
{
    public function bark()
    {
        dd('にゃんにゃん');
    }
}

AnimalIfを利用しているSampleClassはこんな感じです。

<?php

namespace App\Http;

class SampleClass
{
    public $slack;

    public function __construct(AnimalIf $animal){

        $this->animal = $animal;

    }

    public function run(){

        $this->animal->bark();

    }
}

実行してみる。
まずはDogClassを利用してみる。

    app()->bind(\App\Http\AnimalIf::class,\App\Http\DogClass::class);

    // Animalインターフェイスを利用しているsampleClassの依存関係を解決
    app()->bind('sampleClass',\App\Http\SampleClass::class);
    $sampleClass = app()->make('sampleClass');

    $sampleClass ->run(); // わんわん

CatClassを利用する場合はこう。

    app()->bind(\App\Http\AnimalIf::class,\App\Http\CatClass::class);

    // Animalインターフェイスを利用しているsampleClassの依存関係を解決
    app()->bind('sampleClass',\App\Http\SampleClass::class);
    $sampleClass = app()->make('sampleClass');

    $sampleClass ->run(); // にゃんにゃん

ん〜〜まだよくわからないです。。。