171

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()?

Pim Jager
  • 31,965
  • 17
  • 72
  • 98

5 Answers5

248

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.

Demis Palma ツ
  • 7,669
  • 1
  • 23
  • 28
Paul Dixon
  • 295,876
  • 54
  • 310
  • 348
  • 2
    This is how I do it. Note that from within classes you can use parent and self. – Ross Feb 10 '09 at 20:55
  • 1
    On a similar note, you can also do $var = 'Name'; $obj->{'get'.$var}(); – Mario Feb 10 '09 at 21:04
  • 1
    Good point, though that only works for method calls and not constructors – Paul Dixon Feb 10 '09 at 21:16
  • 14
    If you work with namespace, put the current namespace into the string: `$var = __NAMESPACE__ . '\\' . $var . 'Class';` – bastey Sep 02 '13 at 13:28
  • @bastey - but why? I just spent too much time on figuring out, why this wouldn't work without the namespace preceding the class name... – jkulak Feb 13 '17 at 14:38
95

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;
csga5000
  • 4,062
  • 4
  • 39
  • 52
  • 8
    The only working solution when need to create with namespace, are yours. Thanks for share! – Tiago Gouvêa Aug 10 '15 at 22:50
  • But this is just weird, Why would it not use the declared namespace ? – Yisrael Dov Apr 29 '18 at 09:24
  • @YisraelDov Yes it is definitely counter intuitive. But for whatever reason it does behave weirdly in this context. Thanks php – csga5000 May 15 '18 at 21:57
  • @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. – Bence Szalai Jun 27 '19 at 17:52
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.

flu
  • 14,307
  • 8
  • 74
  • 71
32
class Test {
    public function yo() {
        return 'yoes';
    }
}

$var = 'Test';

$obj = new $var();
echo $obj->yo(); //yoes
ReactiveRaven
  • 7,203
  • 2
  • 29
  • 38
zalew
  • 10,171
  • 3
  • 29
  • 32
-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"));
  • 3
    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 http://php.net/manual/en/function.call-user-func-array.php – ChrisN Jan 11 '18 at 12:36