anonymous-php / simple-di
简单的依赖解析和注入容器
Requires
- psr/container: ^1.0
README
实际上,这个库更多的是关于依赖容器,而不是自动装配,但别担心,自动装配是有的。您可以创建具有自动装配参数的类实例,并将依赖注入到调用的方法中。
历史
我非常喜欢PHP-DI,但当开始新的项目时,我意识到它需要另一种确定其定义和依赖的方法。我希望有尽可能简单的定义语法,同时具有强大但又不复杂的注入机制。所以我只是编写了自己的DI。
特性
我不想将任何定义包装在不必要的函数中,这些函数只是将此定义标记为可实例化的类。在编写代码时,我已经知道它是怎么回事,我想决定如何在我的应用程序中使用这些信息。
我的同事询问了我的库中的原始注入。我认为这不是一个好主意。只需为容器设置依赖关系,并获取所需值。自己控制这类值的类型。
兼容性
默认情况下,自动装配是禁用的。
安装
composer require anonymous-php/simple-di
方法
类 Container
实现了 \Psr\Container\ContainerInterface
接口,因此有两个方法: has($id)
,它按常规工作,以及 get($id)
,它可能具有与您首选库不同的行为。还有一个方法 set($id, $value)
,它确实如此。
get($id)
该方法响应原始值,唯一的例外是闭包。在闭包的情况下,库会通过注入其依赖关系来解析它。闭包可以返回任何原始值或任何您希望的类的实例。此方法会缓存解析的结果。
<?php $container = new \Anonymous\SimpleDi\Container([ 'primitive' => 42, 'wrapped-primitive' => function (\Psr\Container\ContainerInterface $c) { return (string)$c->get('primitive'); }, ]); var_dump($container->get('primitive'), $container->get('wrapped-primitive')); // int(42) // string(2) "42"
instantiate($id, array $arguments = [], $instanceOf = null)
此方法创建特定类的实例。它尝试解析定义或在没有定义的情况下实例化提供的类。该方法在每次调用时都会创建一个新的实例。如果闭包作为参数提供,则 instantiate
也会每次都解析它。
<?php interface I {} class A implements I {} class B implements I {} $container = new \Anonymous\SimpleDi\Container([ I::class => A::class, B::class => function () { return new B(); }, ]); var_dump( $container->instantiate(I::class), $container->instantiate(A::class), $container->instantiate(B::class, [], I::class) ); $container->instantiate('C'); /* object(A)#4 (0) { } object(A)#5 (0) { } object(B)#7 (0) { } PHP Fatal error: Uncaught Anonymous\SimpleDi\FactoryException Unresolvable dependency 'C' */
make($id, array $arguments = [], $recreate = false)
几乎与上一个相同,但具有缓存。这意味着您将在每次方法调用中获取相同的实例。如果使用相同的 $id
在 instantiate
之后调用 make
,您将获得已缓存的类实例。
<?php class A {} $container = new \Anonymous\SimpleDi\Container(); var_dump( $container->instantiate(A::class), $container->make(A::class) ); /* object(A)#2 (0) { } object(A)#2 (0) { } */
injectOn($callable, array $arguments = [])
将参数注入到提供的 实例 的方法中,并调用它。如果参数数组不包含调用方法等待的所有变量,则库会尝试解析它们。注意:闭包是一个具有 __invoke
方法的对象,因此您可以在它上使用 injectOn
。
<?php class A { public function e($v) { return $v; } } class B { public function strtoupper($v) { return strtoupper($v); } } $container = new \Anonymous\SimpleDi\Container(); var_dump( $container->injectOn([new A(), 'e'], ['v' => 'value1']), $container->injectOn(function (B $b, $v) { return $b->strtoupper($v); }, ['v' => 'value2']) ); // string(5) "value1" // string(5) "VALUE2"
call($callable, array $arguments = [])
几乎与 injectOn
相同,但它提供了解析和实例化提供类的可能性。
<?php interface Filter { public function __invoke($v); } class Upper implements Filter { public function __invoke($v) { return strtoupper($v); } } interface Output { public function __invoke($v); } class StdOutput implements Output { public function __invoke($v) { echo $v, PHP_EOL; } } class Printer { protected $filter; public function __construct(Filter $filter) { $this->filter = $filter; } public function out(Output $output, $value) { $filter = $this->filter; $output($filter instanceof Filter ? $filter($value) : $value); } } $container = new \Anonymous\SimpleDi\Container([ Output::class => StdOutput::class, Filter::class => Upper::class, ]); $container->call([Printer::class, 'out'], ['value' => 'Text to print 1']); $container->call('Printer::out', ['value' => 'Text to print 2']); // TEXT TO PRINT 1 // TEXT TO PRINT 2
待办事项
- 文档
- 测试
- 性能测量