173

I know this question sounds rather vague so I will make it more clear with an example:

$var = 'bar';
$bar = new {$var}Class('var for __construct()'); //$bar = new barClass('var for __construct()');

This is what I want to do. How would you do it? I could off course use eval() like this:

$var = 'bar';
eval('$bar = new '.$var.'Class(\'var for __construct()\');');

But I'd rather stay away from eval(). Is there any way to do this without eval()?

5 Answers 5

253

Put the classname into a variable first:

$classname=$var.'Class';

$bar=new $classname("xyz");

This is often the sort of thing you'll see wrapped up in a Factory pattern.

See Namespaces and dynamic language features for further details.

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

5 Comments

This is how I do it. Note that from within classes you can use parent and self.
On a similar note, you can also do $var = 'Name'; $obj->{'get'.$var}();
Good point, though that only works for method calls and not constructors
If you work with namespace, put the current namespace into the string: $var = __NAMESPACE__ . '\\' . $var . 'Class';
@bastey - but why? I just spent too much time on figuring out, why this wouldn't work without the namespace preceding the class name...
100

If You Use Namespaces

In my own findings, I think it's good to mention that you (as far as I can tell) must declare the full namespace path of a class.

MyClass.php

namespace com\company\lib;
class MyClass {
}

index.php

namespace com\company\lib;

//Works fine
$i = new MyClass();

$cname = 'MyClass';

//Errors
//$i = new $cname;

//Works fine
$cname = "com\\company\\lib\\".$cname;
$i = new $cname;

5 Comments

The only working solution when need to create with namespace, are yours. Thanks for share!
But this is just weird, Why would it not use the declared namespace ?
@YisraelDov Yes it is definitely counter intuitive. But for whatever reason it does behave weirdly in this context. Thanks php
@YisraelDov I guess it is because in that case instantiating a class from another namespace would be huge headache. Also consider that variables can be passed around. When the classname is written as text into a php file, whoever writes it knows exactly what namespace it is written in. But when a variable is passed between functions, it'd be a nightmare to follow up on it. Also if you use get_class() it'll give back the FQ classname, so that can be stored in a variable straight away and used anywhere. If it was depending on the namespace of the file, it wouldn't work very well.
@BenceSzalai imo counter intuitive functionality isn't worth forced explicitness. I think if I had a bug because of namespaces, it'd be somewhat evident to me and/or if i want to force the namespace I easily can. Those issues seem easier to debug or fix to me than why it doesn't work as one would intuit it should (aka if new MyClass() works then new $"MyClass"() should also work).
64

How to pass dynamic constructor parameters too

If you want to pass dynamic constructor parameters to the class, you can use this code:

$reflectionClass = new ReflectionClass($className);

$module = $reflectionClass->newInstanceArgs($arrayOfConstructorParameters);

More information on dynamic classes and parameters

PHP >= 5.6

As of PHP 5.6 you can simplify this even more by using Argument Unpacking:

// The "..." is part of the language and indicates an argument array to unpack.
$module = new $className(...$arrayOfConstructorParameters);

Thanks to DisgruntledGoat for pointing that out.

Comments

32
class Test {
    public function yo() {
        return 'yoes';
    }
}

$var = 'Test';

$obj = new $var();
echo $obj->yo(); //yoes

2 Comments

No, not a good example. Only works if everything is in the same php file.
2ndGAB should remove this comment. Autoloading has nothing to do with this question.
-1

I would recommend the call_user_func() or call_user_func_arrayphp methods. You can check them out here (call_user_func_array , call_user_func).

example

class Foo {
static public function test() {
    print "Hello world!\n";
}
}

 call_user_func('Foo::test');//FOO is the class, test is the method both separated by ::
 //or
 call_user_func(array('Foo', 'test'));//alternatively you can pass the class and method as an array

If you have arguments you are passing to the method , then use the call_user_func_array() function.

example.

class foo {
function bar($arg, $arg2) {
    echo __METHOD__, " got $arg and $arg2\n";
}
}

// Call the $foo->bar() method with 2 arguments
call_user_func_array(array("foo", "bar"), array("three", "four"));
//or
//FOO is the class, bar is the method both separated by ::
call_user_func_array("foo::bar"), array("three", "four"));

1 Comment

This answer doesn't apply to the question. OP is asking how to INSTANTIATE a class (triggering the class __construct method dynamically) from a variable string and getting the CLASS OBJECT back in a new variable -- your advice will return the VALUE of the class->method([ ]) you're calling, not the class object so doesn't apply for this case. See the return value php.net/manual/en/function.call-user-func-array.php

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.