LaravelでDIを扱う仕組み ~Service ContainerとService Provider~

481be3ccc3d0803b2af6b1dcec4f3876?s=47 2bo
December 05, 2019

LaravelでDIを扱う仕組み ~Service ContainerとService Provider~

481be3ccc3d0803b2af6b1dcec4f3876?s=128

2bo

December 05, 2019
Tweet

Transcript

  1. LaravelでDIを扱う仕組み ~Service ContainerとService Provider~ 19.12.05 @AkogareSe

  2. • @AkogareSe • エンジニア8年目 ◦ SIer->社内エンジニア ◦ PHP歴1年 ◦ Laravel勉強中

    ◦ AWS/Vue.js勉強したい • 旅行好き • IKEAシャークかわいい 自己紹介
  3. 話すこと • Dependency Injection(DI)の簡単な説明 • LaravelでDIを扱うための機能 ◦ Service Container ◦

    Service Provider
  4. DIとは? • 日本語では「依存性の注入」という • オブジェクト指向プログラミングのデザインパターン

  5. 依存とは? • あるクラスの処理が別の具体クラスの存在を前提にしていること ◦ 別クラスのオブジェクトを処理の中で生成すること

  6. 依存の例

  7. Mailer ------------------------------------------------------- send() RecommendService ------------------------------------------------------- recommend() RecommendServiceクラスが Mailerに依存している状態 依存 利用

  8. 依存の何が問題? • 単体テストしづらい ◦ テストの時はメール送りたくない ◦ Mailerにテスト用の分岐処理を追加する • 依存する側の再利用性の低下 ◦

    メールではなく、場合によってSMSで送りたい ◦ RecommendServiceをそのまま利用できない
  9. DI = 利用するオブジェクトを外部から注入 • 利用するオブジェクトを引数で渡す • パターン ◦ コンストラクタ ◦

    メソッド ◦ セッター
  10. DIの例

  11. Mailer RecommendService Mailerに依存していない send()を持つクラスであればよい 利用

  12. DIの効果 • 振る舞いを外部から変えられる ◦ send()さえ実装されていればどんなオブジェクトでもよい ▪ 実際にはメールを送らないもの ▪ SMS送信するもの ▪

    Line送信するもの ▪ etc
  13. DIの課題とコンテナ • 課題 ◦ 注入するオブジェクトの生成をどこでやるか? ◦ オブジェクトが多かったり、入れ子だと生成が大変 ▪ A,B,C ▪

    A->B->C • DIコンテナ ◦ DIに必要な機能を提供するソフト/フレームワーク ◦ 注入するオブジェクトの生成、管理を担う
  14. ここまではわかった

  15. ここからはLaravelの話

  16. Laravel勉強中出会った謎の用語 • “Service Container” と “Service Provider” • どうやらDIに関連するものらしい...?

  17. ドキュメント読んでみた...けど??? • Service Container ❝Laravelのサービスコンテナは、クラス間の依存を管理する強力な管理ツールです。❞ • Service Provider ❝サービスプロバイダは、 Laravelアプリケーション全体の起動処理における、初めの心臓部です。

    ❞ https://readouble.com/laravel/6.x/ja/ より
  18. None
  19. つまり何? • Service Container ◦ DIコンテナ • Service Provider ◦

    Laravelのサービス(機能)の初期化処理を書くクラス ◦ SCへオブジェクトの生成方法を登録する場所として使われる
  20. SCの自動注入機能

  21. Hello ------------------------------------------------------- say() GreetingController ------------------------------------------------------- geet() コントローラメソッドの型宣言を見て オブジェクトを自動で生成/注入 依存 利用

  22. これだと依存したまま

  23. 抽象化する

  24. GreetingInterface ------------------------------------- say() GreetingController ------------------------------------ greet() 依存 Hello -------------------------------------- say()

    実装 GreetingInterfaceに依存するように変更
  25. これだけでは動かない

  26. SCにインターフェイスとオブジェクトの対応を登録 • bind()で登録 • GreetingInterfaceの型指定に対して、Helloオブジェクトを生成・注入させる

  27. 結局Helloに依存?

  28. bind()用の場所がある

  29. Service Provider

  30. Service Provider • register()はSCへのバインド処理を書くための既定メソッド • Laravelの初期化処理時に実行される

  31. まとめ • DI ◦ 利用するオブジェクトを引数で渡してやること ◦ 振る舞いを後から変えられる • DIコンテナ ◦

    DIに必要な機能を提供してくれるもの • Service Container ◦ LaravelのDIコンテナ • Service Provider ◦ SCにオブジェクトの生成ルールを登録するところ
  32. おわり

  33. おまけ

  34. GreetingInterface ------------------------------------- say() GreetingController ------------------------------------ greet() 依存 Hello ------------ say()

    実装 GreetingInterfaceを実装したGoodByeクラスを追加 GoodBye ------------ say() 実装
  35. bind()メソッドにはクロージャを渡すこともできる • クロージャの戻値はSCに生成してほしいインスタンス • 動的なバインドが可能

  36. ほんとのおわり