innmind / di
2.1.0
2024-03-24 14:52 UTC
Requires
- php: ~8.2
Requires (Dev)
- innmind/black-box: ~5.6
- innmind/coding-standard: ~2.0
- vimeo/psalm: ~5.23
This package is auto-updated.
Last update: 2024-08-24 15:43:35 UTC
README
使用单一方式定义服务的最小化依赖注入容器。
此外,没有缓存,因此没有缓存失效问题。
安装
composer require innmind/di
使用
use Innmind\DI\{ Builder, Container, }; $container = Builder::new() ->add('connection', fn(Container $get) => new ConnectionPool( // imaginary class $get('connection_a'), $get('connection_b'), )) ->add('connection_a', fn() => new \PDO('mysql://localhost')) ->add('connection_B', fn() => new \PDO('mysql://docker')) ->build(); $connection = $container('connection'); $connection instanceof ConnectionPool; // true
add
方法接受任何返回 object
的 callable
。这允许您使用匿名函数以提高易用性(但会有内存影响)或使用形式为 [Service::class, 'factoryMethod']
的可调用对象,这样只有在服务加载时才加载类文件。
使用枚举代替字符串来引用服务
当通过 Builder::add()
添加服务时,使用 string
命名服务很简单,但静态分析工具无法确定返回服务的类型。这会导致需要抑制的 混合参数 错误。
相反,您可以使用枚举如下
use Innmind\DI\Service; /** * @template S * @implements Service<S> */ enum Services implements Service { case connection; case connectionA; case connectionB; /** * @return self<ConnectionPool> */ public static function connection(): self { /** @var self<ConnectionPool> */ return self::connection; } /** * @internal * * @return self<\PDO> */ public static function connectionA(): self { /** @var self<\PDO> */ return self::connectionA; } /** * @internal * * @return self<\PDO> */ public static function connectionB(): self { /** @var self<\PDO> */ return self::connectionB; } }
并且可以这样使用它
use Innmind\DI\{ Builder, Container, }; $container = Builder::new() ->add(Services::connection, fn(Container $get) => new ConnectionPool( // imaginary class $get(Services::connectionA), $get(Services::connectionB), )) ->add(Services::connectionA, fn() => new \PDO('mysql://localhost')) ->add(Services::connectionB, fn() => new \PDO('mysql://docker')) ->build(); $connection = $container(Services::connection); $connection instanceof ConnectionPool; // true
技巧
通过使用枚举,您可以轻松地在一个地方引用所有定义的服务。如果您分发您的包,用户可以查看枚举以了解他们可以使用哪些服务(因为您可以声明 @internal
服务)。
此外,服务的名称不再有拼写错误,并且服务会自动命名空间(包之间不可能发生冲突)。
注意
在枚举上使用命名构造函数来指定返回的类。Phantom 不允许在 case
中直接指定模板值。