1

I have two classes which depending on each other:

class A
{
    public function __construct(B $b)
    {
        $this->b = $b;
    }
}
class B
{
    public function __construct(A $a)
    {
        $this->a = $a;
    }
}

And I need to wrap them through Pimple like this:

$c = new \Pimple();
$c['aService'] = function($c){
    return new A($c['bService']);
}
$c['bService'] = function($c){
    return new B($c['aService']);
}

But unfortunately I get cycling:

Fatal error: Maximum function nesting level of '100' reached, aborting!

Is there any way to reach this cross-dependency without cycling? Or I can use only unidirectional dependencies?

4

1 回答 1

1

这让我想起了baboushka的

当然,你一定会在这里得到无限递归。两个函数相互调用,每次返回一个新实例,将调用的返回值传递给它们的函数计数器部分,然后再次调用该函数,该函数再次调用另一个函数,该函数调用....
底线:当您有 2 个从一开始就相互依赖的类 ( __construct) 时,您的设计可能存在缺陷。

您定义这两个构造函数的方式,您将永远无法创建类的实例。仅仅是因为您需要同时实例化两个类。
你不能,你根本不能那样做。

尝试这个:

class A
{
    public $b = null;
    public function __construct(B $b = null)
    {
        $this->b = $b;
    }
    public function setB(B $b = null)
    {
        if ($b === null)
        {
            $b = new B($this);//pass A here
        }
        $this->b = $b;
        return $this;
    }
}
class B
{
    public $a = null;
    public function __construct(A $a = null)
    {
        $this->setA($a);
    }
    public function setA(A $a = null)
    {
        if ($a === null)
        {
            $a = new A($this);//pass B here
        }
        $this->a = $a;
        return $this;
    }
}

通过将构造函数参数的默认值设置为null,传递一个实例就变成了可选的,所以现在你可以这样做:

$a = new A;
$b = new B($a);
//or even:
$bFromA = $a->b;

顺便说一句:总是事先声明你的属性。它会加快你的课

就个人而言,我会使用 gettersetter,并延迟加载依赖项,但我会保持构造函数原样:

class A
{
    //protected, or private. Access this via getter/setter
    protected $b = null;
    public function __construct(B $b = null)
    {
        $this->setB($b);
        return $this;
    }
    //setter, allows injection later on
    public function setB(B $b = null)
    {
        $this->b = $b;//allow to set to null
        return $this;
    }
    //getter, lazy-loader:
    public function getB()
    {
        if ($this->b === null)
        {//create new instance, if b isn't set
            $this->setB(
                new B($this)
            );
        }
        return $this->b;
    }
}
class B
{
    protected $a = null;
    public function __construct(A $a = null)
    {
        $this->setA($a);
        return $this;
    }
    public function setA(A $a = null)
    {
        $this->a = $a;
        return $this;
    }
    public function getA()
    {
        if ($this->a === null)
        {
            $this->setA(
                new A($this)
            );
        }
        return $this->a;
    }
}

使用疙瘩:

$c['aService'] = function($c)
{
    return new A;
};
$c['bService'] = function($c)
{
    return new B;
};
$b = $c->bService;
$b->getA();//works just fine
于 2013-07-19T07:19:30.980 回答