我已经使用了Dice PHP DI container很长一段时间,它在注入依赖项的简单性方面似乎是最好的.
class A {
public $b;
public function __construct(B $b) {
$this->b = $b;
}
}
class B {
}
$dice = new \Dice\Dice;
$a = $dice->create('A');
var_dump($a->b); //B object
但是,当您必须使用直接相互依赖的对象时,由于无限循环,finall结果是服务器错误.
例:
class A {
public $b;
public function __construct(B $b) {
$this->b = $b;
}
}
class B {
public $a;
public function __construct(A $a) {
$this->a = $a;
}
}
Dice的作者说没有办法从A或B类构造一个对象.如:
>’A’对象需要’B’对象才能创建
>但是’B’对象需要’A’对象才能创建
作者说,这个限制涉及所有DI容器!
题:
在不改变初始代码的情况下,很好地克服这个问题的最佳解决方案是什么?任何人都可以提供一个使用其他DI容器的例子,什么时候可以运行exampled代码而不需要庞大的解决方法?
解决方法:
正如您在Dice github(https://github.com/TomBZombie/Dice/issues/7)上的帖子中所提到的,在不删除循环依赖的情况下解决的唯一方法是重构其中一个类以使用setter注入:
class A {
public $b;
public function __construct(B $b) {
$this->b = $b;
}
}
class B {
public $a;
public function setA(A $a) {
$this->a = $a;
}
}
这允许构造对象:
$b = new B();
$a = new A($b);
$b->setA($a);
使用原始代码:
class A {
public $b;
public function __construct(B $b) {
$this->b = $b;
}
}
class B {
public $a;
public function __construct(A $a) {
$this->a = $a;
}
}
您无法构造它并遇到与容器相同的问题:
$b = new B(new A(new B(new A(new B(.............))))
使用诸如ReflectionClass :: newInstanceWithoutConstructor之类的hack使容器解决此问题的问题是您的对象现在依赖于使用此方法的创建逻辑.您基本上将代码耦合到容器,这是一个糟糕的设计,因为您的代码现在不再是可移植的,并且不能在没有容器的情况下使用它来执行对象构造.