Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.
interface IObjectLoader {
public function load($name);
public function into($object);
public function using($method);
public function addObject($objectOrClass, $alias);
public function addInstanceArgs($name, array $args);
}
// usage:
$loader->addObject('MyFramework_User', 'user');
$loader->addInstanceArgs('user', array($session, $auth));
class LoginController {
private $loader;
public function __construct(IObjectLoader $loader) {
$this->loader = $loader;
}
public function setUser(User $user) {
$this->user = $user;
}
public function loginAction() {
$this->loader->load('user')->into($this)->using('setUser');
$this->user->authenticate($username, $password);
// etc
}
}
Well I think it brilliant, but that is almost exactly how Skeleton Framework does it. The Skeleton 'Locator' is a Registry + Loader that has DI functionality like you show. And since it uses itself to load dependencies you can chain them, so a Model can load a dependency on an ActiveRecord class, will in turn load a dependency on a DB Connection class.
In addition, the Skeleton Front Controller also has a plug-in you can use to inject dependencies in to Action Controllers.
arborint wrote:Well I think it brilliant, but that is almost exactly how Skeleton Framework does it. The Skeleton 'Locator' is a Registry + Loader that has DI functionality like you show. And since it uses itself to load dependencies you can chain them, so a Model can load a dependency on an ActiveRecord class, will in turn load a dependency on a DB Connection class.
In addition, the Skeleton Front Controller also has a plug-in you can use to inject dependencies in to Action Controllers.
Funny thing is, in developing ideas I looked at skeleton and thought you were doing it all wrong Maybe I haven't looked good enough. The lack of type hinting was probably what made me stop looking further. I'm going to look further. I now remember too I saw the term "registry" used so I probably came to conclusions too quick.
Looked at your class again. The big difference for me is that you set an object, ask it back and get something. There's no way an object knows what class or interface it is. That's why I disallowed using "get($name)" as a public method (though I use it privately) and only allow it to be set using a method. I see that a user can simply do this without any typehint in the setter. And with simply getting the object like you have it you could still pass it through the setter manually. So maybe I'm too optimistic about what I tried to accomplish.
koen.h wrote:Looked at your class again. The big difference for me is that you set an object, ask it back and get something. There's no way an object knows what class or interface it is. That's why I disallowed using "get($name)" as a public method (though I use it privately) and only allow it to be set using a method. I see that a user can simply do this without any typehint in the setter. And with simply getting the object like you have it you could still pass it through the setter manually. So maybe I'm too optimistic about what I tried to accomplish.
$model = $locator->get('model', 'MyModel');
$model->expectedMethod();
// PHP complains about $model::expectedMethod() not being there in class TotallyDifferentModel
First of all, that is a problem with Registries and nothing to do with DI. And that is a problem with many other types of objects as well. I suppose that not allowing overwrite would be one solution.
Second, you can also do this if you don't want to check first for an object in the Registry: