11

I've some code that creates ad instance with a dynamic class (i.e. from a variable):

$instance = new $myClass();

Since the constructor has different argument count depending on $myClass value, How do I pass a variable list of arguments to the new statement? Is it possible?

1
  • reflection comes to mind Commented Aug 9, 2012 at 13:51

3 Answers 3

14
class Horse {
    public function __construct( $a, $b, $c ) {
        echo $a;
        echo $b;
        echo $c;
    }
}

$myClass = "Horse";
$refl = new ReflectionClass($myClass);
$instance = $refl->newInstanceArgs( array(
    "first", "second", "third"    
));
//"firstsecondthird" is echoed

You can also inspect the constructor in the above code:

$constructorRefl = $refl->getMethod( "__construct");

print_r( $constructorRefl->getParameters() );

/*
Array
(
    [0] => ReflectionParameter Object
        (
            [name] => a
        )

    [1] => ReflectionParameter Object
        (
            [name] => b
        )

    [2] => ReflectionParameter Object
        (
            [name] => c
        )

)
*/
Sign up to request clarification or add additional context in comments.

1 Comment

How to call a method of that class with arguments?
1

I don't know why but i don't like using the new operator in my code.

Here is a static function to create an instance of a class called statically.

class ClassName {
    public static function init(){       
        return (new ReflectionClass(get_called_class()))->newInstanceArgs(func_get_args());        
    }

    public static function initArray($array=[]){       
        return (new ReflectionClass(get_called_class()))->newInstanceArgs($array);        
    }

    public function __construct($arg1, $arg2, $arg3){
        ///construction code
    } 
}

If you are using it inside a namespace you need to escape ReflectionClass like so: new \ReflectionClass...

Now you can call the init() method with a variable number of arguments and it will pass it on to the constructor and return an object for you.

Normal way using new

$obj = new ClassName('arg1', 'arg2', 'arg3');
echo $obj->method1()->method2();

Inline way using new

echo (new ClassName('arg1', 'arg2', 'arg3'))->method1()->method2();

Static call using init instead of new

echo ClassName::init('arg1', 'arg2', 'arg3')->method1()->method2();

Static call using initArray instead of new

echo ClassName::initArray(['arg1', 'arg2', 'arg3'])->method1()->method2();

The nice thing about the static methods is that you can run some pre construction operations in the init methods such as constructor argument validation.

Comments

0

The easiest route would be to use an array.

public function __construct($args = array())
{
  foreach($array as $k => $v)
  {
    if(property_exists('myClass', $k)) // where myClass is your class name.
    {
      $this->{$k} = $v;
    }
  }
}

1 Comment

Yep, thought about that, I was just wondering if another approach was possible. Besides, the property_exists() trick is wonderful, thanks a lot!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.