Thanks for the fast replies.
McGruff, yes, that answers my question, I had some trouble trying to visualise the process.
I looked at a few of the simpler dic examples I found. I noticed that while most were able to provide an easy way to get an object, there didn’t seem to be anyway of passing parameters to the objects.
I come up with this, based on Fabien Potenciers Pimple
class DiContainer
{
protected $_container = array();
public function get($name, array $params = array())
{
if (!isset($this->_container[$name])) {
throw new DiContainer_Exception($name.' does not exist in the container!');
}
return $this->_container[$name]($this, $params);
}
public function __get($name)
{
return $this->get($name, array());
}
public function __call($name, array $params)
{
return $this->get($name, $params);
}
public function set($name, Closure $func)
{
$this->_container[$name] = $func;
}
public function __set($name, Closure $func)
{
$this->set($name, $func);
}
public function asShared(Closure $callable)
{
return function ($c, $params) use ($callable)
{
static $object;
if (null == $object) {
$object = $callable($c, $params);
}
return $object;
};
}
}
Example use
$dic = new Guppy_DiContainer();
$dic->somename = function ($c, $p)
{
return new someobject($c->anotherobject, $p[0], $p[1]);
};
var_dump($dic->somename('param0', 'param1'));
Is this sensible? I feel like I may be missing an obvious issue as it seems most di containers don’t support this.
I think you’re comparing ServiceLocator with dependency injection?
Yes I was. I was struggling to see benefits of this approach, but didn’t want to rule it out. The idea of a SeviceLocator, to me, seems like a glorified registry.
But just to confuse matters… you might need to pass a DI container around like a ServiceLocator. Maybe something needs either a Foo or a Bar but you don’t know which until the app is up and running. That’s the scenario outlined above. The front controller makes a decision, configures the injector, then makes a generic “give me the controller” call. With ServiceLocator, there is no configuration stage: instead the front controller would call different methods to get the appropriate controller object.
You might feel tempted to put some of this decision-making logic in the assembler/injector/container/whatever-you-want-to-call-it. I think you should avoid that. Assembler-things should do the wiring but nothing else. If you need some kind of conditional logic, pass them around to whatever knows how to apply that logic. Of course I could be wrong.
My temptation would be to do something like this (based on my above code).
$dic->controller = function ($c, $p)
{
return new $p[0].'_Controller'();
};
That seems really messy though. Another idea would be to have a sub-container for all the different controllers. That seems like a maintenance nightmare, although it does sound more like the right way to do it.
I think my best bet is to build a basic framework utilising di. That way I’ll have a better idea of what issues can arise so I can develop with those in mind if I decide to use di in any client sites.
Best Regards, George