Slim4でDIコンテナ(PHP-DI)を導入する
2024/01/29
DIコンテナを利用すると、ルートに登録したコールバック関数の引数でクラス名を指定すると、インスタンスが自動で渡されるようになります(依存注入)。複雑なインスタンス化プロセスもDIコンテナに設定することができます。例えば、コールバック関数の処理に入る前にDBへの接続をしておくといった使い方ができます。
```php
/** @var Slim\App $app */
$app->get('/', function (Doctrine\DBAL\Connection $conn) {
// $connにDoctrine\DBAL\Connectionのインスタンスが代入されている
$result = $conn->fetchAssociative('SELECT ...');
});
```
## 導入手順
まず、Composerで[PHP-DI](https://github.com/PHP-DI/PHP-DI)をインストールします。Slim4専用に用意されたものがあるので、そちらを使用します。
```bash
composer require php-di/slim-bridge
```
Composerでインストールしたら、次にSlim\Appクラスの生成方法を変更します。あらかじめ依存解決のルールを定義しておく必要があります。
```diff
+ $containerBuilder = new DI\ContainerBuilder();
+ $containerBuilder->addDefinitions([
+ // ここで依存解決のルールを定義します
+ ]);
+ $container = $containerBuilder->build();
- $app = Slim\Factory\AppFactory::create();
+ $app = DI\Bridge\Slim\Bridge::create($container);
/** @var Slim\App $app */
$app->get('/', function (Doctrine\DBAL\Connection $conn) {
// $connにDoctrine\DBAL\Connectionのインスタンスが代入されています
$result = $conn->fetchAssociative('SELECT ...');
});
$app->run();
```
## 依存解決ルールの定義
最も簡単な定義方法は、クラス名とインスタンスを直接紐づける方法です。
```php
$containerBuilder->addDefinitions([
MyClass::class => new MyClass('hoge'),
]);
```
しかし、こちらの定義方法は**非推奨**になっています。必要不必要に関わらずHTTPリクエストがあるたびにインスタンスを生成してしまうためです。必要になった時だけインスタンスを生成する**lazy-loading**のための定義は以下のようになります。
```php
$containerBuilder->addDefinitions([
MyClass::class => DI\create(MyClass::class)->constructor('hoge'),
// または
MyClass::class => function () {return new MyClass('hoge');},
]);
```
ほかにも便利な機能がたくさん用意されているので、詳しく知りたい方は[公式ドキュメント](https://php-di.org/doc/php-definitions.html)を参照してください。