Upgrade to Pro — share decks privately, control downloads, hide ads and more …

php-conference-nagoya-2025

 php-conference-nagoya-2025

PHP カンファレンス名古屋 2025 に登壇したときの資料です
https://fortee.jp/phpcon-nagoya-2025/proposal/f3659e68-1b52-4b22-af02-01a62eaed874

#トークタイトル
PSR と各ライブラリ実装から DI コンテナの要件を整理する

#トーク概要
Laravel・Symfony をはじめとする PHP のフルスタックフレームワークの多くは、DI コンテナを提供しています。
もちろん、そのようなフレームワークを使わなくても、PHP の DI ライブラリ は OSS として利用できるものがたくさんあるため、適宜導入が可能です。

もはや我々にとってなくてはならぬ存在となった DI コンテナですが、みなさん一度は自分で作ってみたいと思ったことがあるのではないでしょうか?

このセッションでは、最低限、どのような要件を満たせば DI コンテナと言えるのか、PHP で広く知られる規約であるPSRの定義を起点に、各種フレームワーク・ライブラリの実装を追いかけながらなんちゃって DI コンテナの要件定義をやってみようと思います。

ふわせぐ

February 22, 2025
Tweet

More Decks by ふわせぐ

Other Decks in Technology

Transcript

  1. 2 PHPカンファレンス名古屋2025 • 竹下 拓秀 / ふわせぐ (@fuwasegu) • 株式会社ゆめみ

    – コーポレートエンジニア – PHP テックリード • PHP / Laravel がメイン – フロントなら Svelte(TS) が好き • 長崎県出身 / 愛知県日進市在住 • (5歳・0歳)の父(26歳) 自己紹介 メ タ 原 則
  2. • フレームワークがよしなにやってくれてる魔法の 仕組みを理解できる – インスタンスの管理 – オブジェクトのライフサイクル(スコープ) – 依存解決 •

    言語仕様の理解が深まる – リフレクション – 動的オブジェクト生成 6 DI コンテナを自作するモチベ PHPカンファレンス名古屋2025
  3. 13 依存性注入(DI)による改善 PHPカンファレンス名古屋2025 • MailerInterface に抽象化 – Smtp 以外のメールにも対応可能 •

    依存をコンストラクタから設定 – オブジェクトの生成と利用が分離された – NotificationService のインスタンスを作るときに Mailer の実装を決定できるように – もちろんモックの注入も可能
  4. • とにかく new が多い! – どこかでインスタンスの生成は必要とは言え... – ネストが深ければ深いほど,依存クラスが多けれ ば多いほど,大量に new

    が必要 • 変更に弱い – コンストラクタのシグネチャー変更に弱い – new している箇所すべての変更が必要 16 手動 DI の限界 PHPカンファレンス名古屋2025
  5. • php-fig/container – PSR-11 で定義される DI コンテナのインタフェース • illuminate/container –

    Laravel で利用されている DI コンテナ • symfony/dependency-injection – Symfony FW のコンポーネントとして提供される DI コンテナ • PHP-DI/PHP-DI – スタンドアロンでも利用しやすい DI ライブラリ 20 調査対象の DI ライブラリ PHPカンファレンス名古屋2025
  6. • php-fig/container – PSR-11 で定義される DI コンテナのインタフェース 21 調査対象の DI

    ライブラリ PHPカンファレンス名古屋2025 とりあえず PSR を確認してスタートラインを決める
  7. • get(string $id): mixed メソッド – 識別子に対応するオブジェクトを取得する – 識別子がなければ例外をスローする –

    取得は冪等であるべきだが,かならずそうとは限らな い(都度生成されるかもしれない) • has(string $id): bool メソッド – 識別子があるか確認 – false な場合,get() は必ず例外をスローする 23 php-fig/container PHPカンファレンス名古屋2025
  8. • 登録できないと取得できないよねという発想 • “登録する”をもう一段階分解すると – インスタンスを登録する – クラス名を登録する • 取得されるとき/登録されるときに

    new する(登録+生成) • ただし依存が絡むと難しいのでまずはシンプルなもののみ 29 オブジェクトが登録できる PHPカンファレンス名古屋2025
  9. 依存解決(Autowiring)まとめ • どのライブラリでも Autowiring はできる – コンストラクタの引数の型を解析 – 特に Laravel・PHP-DI

    では簡単に全自動が可能 • 依存がネストしていも問題なし! じゃぁ Interface やスカラー値では...? PHPカンファレンス名古屋2025 46
  10. • オブジェクトは new $class_string() でいけた • スカラー値はそうはいかない • でもスカラー値を注入したいことは多々ある –

    Config 系とか • Test 時は API の URL を example.com に変えたりと かしたい – しきい値とか 50 スカラー値が注入できる PHPカンファレンス名古屋2025
  11. • 依存性逆転のために Interface に依存させる ケースは多い • でも Interface は new

    できない – Autowiring のとき実体クラスが分からないので困 る • どこかで「Interface → 実体クラス」の対応を どこかで決めてあげないといけない 59 Interface のバインド PHPカンファレンス名古屋2025
  12. • Intarface に依存する場合,どの実装を注入 するかコンテナに明示的に登録が必要 • 各ライブラリで Interface の登録は可能 • 方法として,バインドとエイリアスがある

    – バインド・・・どうやって生成するかを登録 – エイリアス・・・既存のサービスに別名を貼る 65 Interface のバインド まとめ PHPカンファレンス名古屋2025
  13. • ライフサイクルの制御 – get() されたら都度新しくインスタンスを作る(Transient) – 一度 new したらそれを使い回す(Singleton) –

    Laravel はデフォルトが Transient,Symfony はデフォルト が Singleton • Contextual Binding – 一つに Interface に対して実装の選択肢が複数ある場合, コンテキストによってバインドする実装を変えられる 68 他にも DI コンテナの機能は盛りだくさん PHPカンファレンス名古屋2025
  14. • 識別子を指定してオブジェクトを取得できる • 識別子を指定してオブジェクトの有無を確認できる • 識別子に対応するオブジェクトを登録できる – インスタンス / クラス名

    のどちらでも登録可能 • Autowiring できる – 再帰的に解析 • スカラー値を注入できる • Interface がバインドできる 70 作りたい機能がこんなに PHPカンファレンス名古屋2025
  15. • 識別子を指定してオブジェクトを取得できる • 識別子を指定してオブジェクトの有無を確認できる • 識別子に対応するオブジェクトを登録できる – インスタンス / クラス名

    のどちらでも登録可能 • Autowiring できる – 再帰的に解析 • スカラー値を注入できる • Interface がバインドできる 71 作りたい機能がこんなに PHPカンファレンス名古屋2025 実装難易度に結構差があるので 松・竹・梅 でレベル分けしてみる
  16. • 任意のインスタンスを登録できる – 識別子を key にインスタンスの map を内部にもつ • 任意のクラス(依存無し)を登録できる

    – new $class_string() するだけ • PSR-11 に準拠したオブジェクトの取得と確認 – 識別子を key に内部の map から取り出す 72 要件: 松 PHPカンファレンス名古屋2025
  17. • Interface をバインドできる – クラス名での登録とほぼ同じ • スカラー値を注入できる – バインドの設定の拡張 •

    ライフサイクル管理(Optional) – Singleton / Transient を選べるように 73 要件: 竹 PHPカンファレンス名古屋2025
  18. • Autowiring できる – アプローチは2通り A) あらかじめ依存関係の設定ファイルを書かせる B) Reflection で再帰的にコンストラクタを解析

    • Contextual Binding(Optional) – いまなんのクラスを生成中かを把握する仕組み – コンテキスト -> 依存 -> 値 のマッピング – 自作するにはちょっとマニアックなので Optional で 74 要件: 梅 PHPカンファレンス名古屋2025
  19. • php-fig/container – Copyright (c) 2013-2016 container-interop, 2016 PHP Framework

    Interoperability Group – License: MIT License (https://github.com/php-fig/container/blob/master/LICENSE) • illuminate/container – Copyright (c) Taylor Otwell – License: MIT License (https://github.com/illuminate/container/blob/master/LICENSE.md) • symfony/dependency-injection – Copyright (c) 2004-present Fabien Potencier – License: MIT License (https://github.com/symfony/dependency-injection/blob/7.2/LICENSE) • PHP-DI/PHP-DI – Copyright (c) Matthieu Napoli – License: MIT License (https://github.com/PHP-DI/PHP-DI/blob/master/LICENSE) 76 Copyright and License PHPカンファレンス名古屋2025