「プロフェッショナルWebプログラミングLaravel」の感想・備忘録4

スポンサーリンク

サービスコンテナ

依存性の注入(DI)とは

  • クラス内で使う他のクラスのインスタンスをクラス外から受け取ることを依存性の注入(DI)と言う。
  • DIすることで、別クラスに依存しないクラスとすることができ、別クラスの完成を待たずに実装や単体テストを行うことができるようになる。
  • 以下の例では、クラスAがクラスBに依存している状態自体は変わらないが、依存性の注入ではクラスBのインスタンスをコンストラクタで受け取るようになっている。
    これによりクラスAのインスタンス生成はnew classA()ではなくnew classA($classB)となる
// クラスAがクラスBに依存している場合
classA {
    private $classB;
    public function __construct()
    {
        $this->classB = new classB();
    }
}
// 依存性の注入
classA {
    private $classB;
    public function __construct(classB $classB)
    {
        $this->classB = $classB();
    }
}

サービスクラスを生成して依存性を取り除く

app/Http/Controllers/Tweet/IndexController.phpの以下の処理はTweetクラスに依存している状態なので、これをサービスクラスに切り出す。

public function __invoke(Request $request): View
{
    return view('tweet.index', ['tweets' => Tweet::orderBy('created_at', 'DESC')->get()]);
}
namespace App\Services;

use App\Models\Tweet;

class TweetService
{
    public function getTweets()
    {
        return Tweet::orderBy('created_at', 'DESC')->get();
    }
}

app/Http/Controllers/Tweet/IndexController.phpは以下のようになり、今度はTweetServiceクラスに依存した状態となる。

public function __invoke(Request $request): View
{
    $tweetService = new TweetService();
    return view('tweet.index', ['tweets' => $tweetService->getTweets()]);
}

サービスクラスを生成して依存性を取り除く

さらにTweetServiceクラスを外部から受け取るようにする。
Laravelのサービスコンテナの力により、これだけで依存性の注入を実現することができる。

public function __invoke(Request $request, TweetService $tweetService): View
{
    return view('tweet.index', ['tweets' => $tweetService->getTweets()]);
}
  • このようにコンストラクタやメソッドの引数で指定された型宣言を判断し、自動でインスタンスを注入してくれる仕組み・クラスをDIコンテナと呼ぶ。
  • LaravelのサービスコンテナはDIコンテナの役割も持っている。

コメント