PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!
I have a abstract class which has a getinstance function in. The problem I have is with arguments. Right now I am using an eval to pass those arguments to the class constructor. Is there a better way to do this.
abstract class Core {
/**
* Arry of the class instances
*
* @var array
*/
static protected $_instances = array();
/**
* Retrieves the singleton instance of this class.
* This is completely self loading
*
* @return instance of this class
*/
static public function getInstance() {
//Get the called class so we know which class to load
$class = get_called_class();
//If there is not an already loaded instance
if (!isset(self::$_instances[$class])) {
//If there were no passed in arguments
if (func_num_args() == 0) {
//Make the new class instance
self::$_instances[$class] = new $class();
} else {
//--------------- HERE! ------------------
$args = func_get_args();
$eval = 'self::$_instances[$class] = new $class(';
for ($i = 0, $count = func_num_args(); $i < $count; ++$i) {
$eval .= '$args['.$i.'],';
}
$eval = substr($eval, 0, -1);
$eval .= ');';
eval($eval);
}
}
return self::$_instances[$class];
}
}
Well I found that you can use a reflectiveclass to accomplish this. The only issue then is I have to allow the constructor to be public which is fine just allows the ability to new a class instead of running the getInstance method.
abstract class Core {
/**
* Arry of the class instances
*
* @var array
*/
static protected $_instances = array();
/**
* Retrieves the singleton instance of this class.
* This is completely self loading
*
* @return instance of this class
*/
static public function getInstance() {
//Get the called class so we know which class to load
$class = get_called_class();
//If there is not an already loaded instance
if (!isset(self::$_instances[$class])) {
//If there were no passed in arguments
if (func_num_args() == 0) {
//Make the new class instance
self::$_instances[$class] = new $class();
} else {
if (method_exists($class, '__construct') === false) {
trigger_error('Constructor for the class (' . $class . ') does not exist, thus you cannot pass arguments to it', E_USER_ERROR);
}
$args = func_get_args();
$reflectionObj = new \ReflectionClass($class);
self::$_instances[$class] = $reflectionObj->newInstanceArgs($args);
}
}
return self::$_instances[$class];
}
}
eval() is the devil, and reflection is very expensive.
The has all the telltale signs of a design smell. Is your "core" class supposed to be inherited by any object that wishes to implement the singleton pattern? My first suggestion would be that the singleton getInstance() method should be implemented by the child class itself, which avoids the complexity of having to dynamically create instances with parameters, and allows for a proper inheritance hierarchy if necessary.
The instance is only called once. It appears at least in my testing that eval and reflection both "cost" about the same. Speed wise there is no difference.