0

i have simple app and i'm trying to start using DI container. I downloaded Pimple, studied the code and documentation. After a while i have come to funny thing. I have two classes, which in special cases communicate between themselves.

class Foo
{
    /**
     * @var Bar 
     */
    private $bar;

    public function __construct(Bar $bar)
    {
        $this->bar = $bar;
    }
}

class Bar
{
    /**
     * @var Foo 
     */
    private $foo;

    public function __construct(Foo $foo)
    {
        $this->foo = $foo;
    }
}

I have defined Pimple container, with two classes, like this:

$container = new Pimple\Container();
$container['foo'] = function($c)
{
    return new Foo($c['bar']);
};
$container['bar'] = function($c)
{
    return new Bar($c['foo']);
};

Here is var_dumped container:

object(Pimple\Container)[14]
  private 'values' => 
    array (size=2)
      'foo' => 
        object(Closure)[17]
      'bar' => 
        object(Closure)[18]
  private 'factories' => 
    object(SplObjectStorage)[15]
  private 'protected' => 
    object(SplObjectStorage)[16]
  private 'frozen' => 
    array (size=0)
      empty
  private 'raw' => 
    array (size=0)
      empty
  private 'keys' => 
    array (size=2)
      'foo' => boolean true
      'bar' => boolean true

The problem is, when i create use $container['foo'], it try to inject class Bar, which require foo, so there's error with Maximum nesting. My idea is, why there is not passed closure? Which will be executed when it will be really needed in class?

Or did I complettly misunderstood what closure is?

M.Svrcek
  • 5,485
  • 4
  • 25
  • 33
  • Seem to be a case of _"Which came first? The chicken or the egg?"_ In your case you aren't really passing a closure, you are getting the returned contents. This is how factories work. Your specific problem lies in that both `Foo` or `Bar` require each other, so constructing either causes the other to be constructed..... _endlessly_. My suggestion is to modify your classes to use setter injection instead and not through the constructor. – Crackertastic Oct 09 '14 at 13:43
  • @Crackertastic When I start using setter injection I may end with unmaintainable code for someone else, because he will need to learn all the dependencies...or am I wrong? – M.Svrcek Oct 09 '14 at 14:01
  • Well, you could always use a type hint so that errors get thrown if they use the wrong object. Of course, if you are going to be distributing your library I would imagine you would write up some documentation laying out the specs for how to work with the library. Another thing you could do is provide public methods that allow the two objects to talk. – Crackertastic Oct 09 '14 at 14:09
  • @PaulCrovella well, that is the question, if I use for example singleton, i create instance of second object in times where first object already instance have...one of them must be first...thats why i want to pass closure to object and first of them will create the second...or no? – M.Svrcek Oct 10 '14 at 05:22

0 Answers0