在本例中,我将classA和classB与pimple容器一起使用。
它们都是相互依赖的。然而,当使用pimple DIC设置时,下面的代码会导致无限循环...
一定有办法在粉刺中做到这一点,但我在文档中看不到…有什么办法防止无限循环吗?
// PIMPLE CONTAINER
use Pimple\Container;
$container = new Container();
use Classes\ClassA;
$container['ClassA'] = function ($c) {
return new ClassA($c['ClassB']);
};
use Classes\ClassB;
$container['ClassB'] = function ($c) {
return new ClassB($c['ClassA']);
};发布于 2017-03-08 15:11:11
严格地说,你的问题与粉刺无关。
你只有一个循环构造函数依赖,没有办法修复它们。A需要B需要A需要B。
问题是,通常情况下,两个相互依赖的类没有多大意义。但在极少数情况下,这两种方法中的一种应该是较轻的依赖项,即在实例化之后通过setter或类似的机制注入对象。
通过在ClassB中传递容器和实例化,您隐藏了依赖项,这超出了拥有依赖项注入容器的目的。现在ClassB依赖于Container,而不是您首先想要的ClassA。
不要这样做,只需向ClassB添加一个方法setA(Class A $a)即可。
然后,在实际需要时通过调用$b->setA($container['ClassA']);来注入依赖项,而不是在DI容器上。作为Adam points out,您甚至可以通过扩展您的服务并在服务定义上使用setter来在容器中进行setter注入。
但是,再次重申,你的主要问题是有一个循环依赖。再想一想。这很可能是你的设计需要改进的一个标志。
发布于 2017-03-08 15:13:04
@yivi首先对循环引用的有效性进行了有效的观察in their answer。所以我真的认为你应该在这里评估你的设计。你可能是在治疗症状,而不是潜在的问题。我们不可能对此发表评论,尽管给出了您的通用示例代码(这是针对手头问题的好代码)。如果你认为你的设计是值得的,也许可以提出一个新的问题?要么在这里,要么在Code Review上?
如果您控制着ClassA和ClassB的设计,那么这种事情的规定方法就是使用setter注入,而不是构造函数注入。
这应该是可行的:
// PIMPLE CONTAINER
use Pimple\Container;
$container = new Container();
use Classes\ClassA;
$container['ClassA'] = function ($c) {
return new ClassA();
};
use Classes\ClassB;
$container['ClassB'] = function ($c) {
return new ClassB();
};
$container->extend('ClassA', function ($instanceOfA, $container) {
$instanceOfA->setB($container['ClassB']);
return $instanceOfA;
});
$container->extend('ClassB', function ($instanceOfB, $container) {
$instanceOfB->setA($container['ClassA']);
return $instanceOfB;
});(未经测试,可能包含拼写错误,但这是一般要点)
请注意,原始构造函数不再接受依赖项,依赖项的插入将留给特定的setter。这允许您在容器中创建服务,然后使用extend调用相关的设置器,在此之后插入依赖项。
这是在文档中:Modifying Services after Definition。
发布于 2017-03-08 12:23:07
// PIMPLE CONTAINER
use Pimple\Container;
$container = new Container();
use Classes\ClassA;
$container['ClassA'] = function ($c) {
return new ClassA($c['ClassB']);
};
use Classes\ClassB;
$container['ClassB'] = function ($c) {
return new ClassB($c);
};将容器传递给classB,而不是从ClassB实例化ClassA。然后,当您在ClassB中需要ClassA时,您可以使用传递给它的容器来启动/获取ClassA的实例。
https://stackoverflow.com/questions/42662808
复制相似问题