Link to home
Start Free TrialLog in
Avatar of Bryan_Heath

asked on

Better way to dynamically load instance w/ args

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:
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 .= ');';


                return self::$_instances[$class];

Open in new window

Avatar of Dushan Silva
Dushan Silva
Flag of Australia image

I think you should put  eval($eval) inside the loop, because this code will evaluate as php code and create new instance of only the last argument as the class name on the end of the loop. Are you using any common framework or in house build one?

Avatar of Bryan_Heath


I don't understand your comment as that's not the case.  It will evaluate the to php code creating a new class passing in all the arguments.  For example:

class Test extends Core {
        public function __construct($foo, $bar) {

$test = Test::getInstance('foo', 'bar');

Open in new window

This example will work because the $eval will be:
self::$_instances[$class] = new $class($arg[0], $arg[1]);

Open in new window

So it works perfectly fine and not my question.  

My question was is there a better way to do this since this seems sort of hackish.  Using eval always makes me nervous.
Oh and this is in house framework
Avatar of Member_2_248744
Flag of United States of America image

Link to home
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I thought of using an array but I was trying to keep the constructor clean as this will be the core of 99% of the classes I will be using.  Though a possibility I want to not do that if I can.

However looking at call_user_func for possible solutions (thank you) I found this:
				$args = func_get_args();
				$reflectionObj = new \ReflectionClass($class);
				self::$_instances[$class] = $reflectionObj->newInstanceArgs($args);

Open in new window

Which works. I wonder which is faster?
you ask "I wonder which is faster?" - - If it works, I would not think that performance (process speed) would be much of a consideration, since it is unlikely it would be used in a large loop executed many times. I always try and use faster code methods, but in php, a scripted language, it is not worth the trouble sometimes to squeak out a slightly faster bit of code.

But I have no idea about the speed, and I would guess,  the only way to really find out is to set up a timed test.

Also thanks for showing me the ReflectionClass, I had not come across that, and it looks very useful for stretching a class, it must be new, many of the methods have no documentation listed.
I would really recommend you have a look at the func_get_args reference page:

There are numerous comments relating to how to get args sanitized, as well as referenced args...which would be a much safer bet than using eval. Eval is so dangerous if your input gets tainted. You don't want any tainting so make sure it's safe before processing, otherwise catastrophic things could happen on your box that you wouldn't even want to consider. These are the types of exploits that script kiddies oogle over.

I also highly recommend the tiny book by O'Reilly called Essential PHP Security isbn #059600656x
@Slick812 - Both eval and reflective have the same run time and but appear to use roughly the same resources.  Though obviously reflective seems like a much better choice.

@ingwa - I agree and don't want to use eval.  Which is the entire point of my post.  See my first reply.
Hi Bryan, great to see you are on board with getting rid of eval. If you take a look at the link I provided, you will find the best real world examples for the function, as well as all other functions. I believe the comment I made reference to about referenced args would be the lines you would want to take.

On another note, I wouldn't be too concerned with any hits on performance if you are able to ensure security all the way. It would be better to take a performance hit rather than loose your entire server, or have hackers hijack it for illegitimate means. Server hardware has become cheaper recently and adding space, ram and processor power is much more affordable than it used to be. Rackspace also has some really great cloud based servers that you may find useful if you find you need more power.

Hope this helps.
Though I understand your concern you seem to misunderstand how this class will be used.  This makes a class instance thus insuring singleton methodology.  As such I have no idea what the args might be as they will be passed in when a new class is created.  Thus making sanitizing them nearly impossible.  Also the args passed in are merely being pushed off to the parent class.  So if there is a problem its on the side where the class is being created and should be secured there, not here.

As to referencing the args that doesn't make sense in PHP 5.  See the very first note on your link.
I found the solution with help from his response