vpa/di

PHP 8.x 的简单依赖注入(DI)实现,使用属性 #[Injectable]

v0.4 2023-01-11 23:11 UTC

This package is auto-updated.

Last update: 2024-09-12 03:03:08 UTC


README

Latest Stable Version Total Downloads Latest Unstable Version License PHP Version Require Scrutinizer Code Quality Code Coverage Build Status Code Intelligence Status

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);