Better way to dynamically load instance w/ args

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!

Moderator: General Moderators

Post Reply
User avatar
Technocrat
Forum Contributor
Posts: 127
Joined: Thu Oct 20, 2005 7:01 pm

Better way to dynamically load instance w/ args

Post by Technocrat »

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.

See there HERE! part:

Code: Select all

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];
	}
}
User avatar
Technocrat
Forum Contributor
Posts: 127
Joined: Thu Oct 20, 2005 7:01 pm

Re: Better way to dynamically load instance w/ args

Post by Technocrat »

/bump
User avatar
Technocrat
Forum Contributor
Posts: 127
Joined: Thu Oct 20, 2005 7:01 pm

Re: Better way to dynamically load instance w/ args

Post by Technocrat »

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.

Updated code:

Code: Select all

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];
	}
}
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Re: Better way to dynamically load instance w/ args

Post by John Cartwright »

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.
User avatar
Weirdan
Moderator
Posts: 5978
Joined: Mon Nov 03, 2003 6:13 pm
Location: Odessa, Ukraine

Re: Better way to dynamically load instance w/ args

Post by Weirdan »

John Cartwright wrote:eval() is the devil, and reflection is very expensive.
Well, in this case it only called once per class - thus it's unlikely there would be a lot of calls to reflection here.
User avatar
Technocrat
Forum Contributor
Posts: 127
Joined: Thu Oct 20, 2005 7:01 pm

Re: Better way to dynamically load instance w/ args

Post by Technocrat »

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.
Post Reply