vpa / di
PHP 8.x 的简单依赖注入(DI)实现,使用属性 #[Injectable]
v0.4
2023-01-11 23:11 UTC
Requires
- php: >=8.0
Requires (Dev)
- phpunit/phpunit: ^9.5
- vimeo/psalm: ^4.8
This package is auto-updated.
Last update: 2024-09-12 03:03:08 UTC
README
PHP 8.x 的依赖注入模式实现 PSR-11 (Psr\Container\ContainerInterface)
要指定可以应用此模式的类,可以使用属性,这种属性支持是 PHP 8 新增的。此实现允许您完全控制可以应用 DI 的类,就像 Angular 或 NestJS 一样。
安装
composer require vpa/di
示例:
require_once(__DIR__ . '/../vendor/autoload.php');
use VPA\DI\Container;
use VPA\DI\Injectable;
#[Injectable]
class A {
function __construct() {}
function echo () {
print("\nThis is Sparta!\n");
}
}
#[Injectable]
class B {
function __construct(protected A $a) {}
function echo () {
$this->a->echo();
}
}
class C {
function __construct(protected A $a) {}
function echo () {
$this->a->echo();
}
}
$di = new Container();
$di->registerContainers();
$b = $di->get(B::class); // returns instance of class B
$b->echo();
$c = $di->get(C::class); // returns exception (class C not tagged as Injectable)
$c->echo();
您可以手动添加别名类,但这些类的声明仍然必须包含 #[Injecatble] 标签。
$di = new Container();
$di->registerContainers(['E'=>A::class]);
$e = $di->get('E');
echo $e instanceof A; // returns true
如果您的类具有带有参数的构造函数(并且这些参数的类型不是对象),则可以将这些参数作为 get 方法的第二个参数以数组的形式传递
#[Injectable]
class A {
function __construct() {}
}
#[Injectable]
class B {
function __construct(protected A $a, private int $x, private int $y) {}
}
$di = new Container();
$di->registerContainers();
$b = $di->get(B::class,['x'=>10,'y'=>20]);
属性 Injectable 的冒泡传播
在 0.2.0 版本中添加了方法 setBubblePropagation(bool $bubblePropogation)
(默认为 true),指定是否应检查父类中是否存在属性 Injectable。这允许您不需要为所有应进行 DI 的子类设置属性 Injectable。
示例
// In versions less 0.2.0 code below returns Exception, in version 0.2.0 and great - will return the desired class
#[Injectable]
class A {}
class B extends A {} // this class is not marked with the attribute Injectable
$di = new Container();
$di->registerContainers();
$b = $di->get(B::class);
与前面的点类似,DI 还支持接口的冒泡传播。
// In versions less 0.2.0 code below returns Exception, in version 0.2.0 and great - will return the desired class
#[Injectable]
interface A {}
class B implements A {} // this class is not marked with the attribute Injectable
$di = new Container();
$di->registerContainers();
$b = $di->get(B::class);