Hi everyone,
Dependency Injection is a very trendy subject and after reading about it I
kinda thought about rewriting the framework I'm doing with dependency
injection. So I made my own implementation and was wondering what would you
think about it? I have followed the article of Martin Fowler (
http://martinfowler.com/articles/injection.html)
with this implementation I have the following :
- you have both constructor and setter injection
- the Dependency class is a service locator
- we have at the same time service locator AND dependency injection
- you can always manually inject dependency
- you can pass arguments to the injected object constructor
So: am I missing something? Do you think it's good enough?
here is the code :
<?php
class Dependency {
protected $_singletonInstances = array();
protected $_setInstances = array();
protected $_configuration;
public static function getInstance() {
static $instance = NULL;
if (NULL === $instance) {
$instance = new static();
}
return $instance;
}
public function setConfiguration(array $configuration) {
$this->_configuration = $configuration;
}
public function getConfiguration() {
return $this->_configuration;
}
public function __isset($serviceName) {
return isset($this->_serviceInstances[$serviceName]);
}
public function __call($serviceName, $args) {
// singleton
if (isset($this->_configuration[$serviceName]) &&
$this->_configuration[$serviceName]['singleton']) {
if (!isset($this->_singletonInstances[$serviceName])) {
$rc = new
\ReflectionClass($this->_configuration[$serviceName]['class']);
$this->_singletonInstances[$serviceName] = empty($args) ?
$rc->newInstance() : $rc->newInstanceArgs($args);
}
$ret = $this->_singletonInstances[$serviceName];
} else {
// normal
if (isset($this->_setInstances[$serviceName])) {
$ret = $this->_setInstances[$serviceName];
unset($this->_setInstances[$serviceName]);
} else {
$rc = new
\ReflectionClass($this->_configuration[$serviceName]['class']);
$ret = $this->_singletonInstances[$serviceName] =
empty($args) ? $rc->newInstance() : $rc->newInstanceArgs($args);
}
}
return $ret;
}
public function __get($serviceName) {
return $this->__call($serviceName, array());
}
public function __set($serviceName, $instance) {
if (!is_object($instance))
throw new Exception('instance must be an object');
$this->_setInstances[$serviceName] = $instance;
}
}
class DependencyInjectorException extends \Exception {
}
$di=DependencyInjector::getInstance();
$di->setConfiguration(array(
'database.connector'=>array(
'singleton'=>true,
'class'=>'DatabaseConnector'
),
'database'=>array(
'singleton'=>true,
'class'=>'Database'
)
));
class DatabaseConnector{}
class Database{
protected $_connector;
public function __construct(){
$this->setConnector(DependencyInjector::getInstance()->{'database.connector'});
}
public function setConnector($connector){
$this->_connector=$connector;
}
}
class Test{
protected $_database;
public function __construct(){
$this->setDatabase(DependencyInjector::getInstance()->database);
}
public function setDatabase($db){
$this->_database=$db;
}
public function getDatabase(){
return $this->_database;
}
}
$test=new Test();
var_dump($test->getDatabase());
?>