283

I have two classes, class ClassOne { } and class ClassTwo {}. I am getting a string which can be either "One" or "Two".

Instead of using a long switch statement such as:

switch ($str) {
    case "One":
        return new ClassOne();
    case "Two":
        return new ClassTwo();
}

Is there a way I can create an instance using a string, i.e. new Class("Class" . $str);?

6 Answers 6

593

Yes, you can!

$str = 'One';
$class = 'Class'.$str;
$object = new $class();

When using namespaces, supply the fully qualified name:

$class = '\Foo\Bar\MyClass'; 
$instance = new $class();

You can also call variable functions & methods dynamically.

$func = 'my_function';
$parameters = ['param2', 'param2'];
$func(...$parameters); // calls my_function() with 2 parameters;

$method = 'doStuff';
$object = new MyClass();
$object->$method(); // calls the MyClass->doStuff() method. 
// or in one call
(new MyClass())->$method();

Also PHP can create variables with a string as well, but it's a really bad practice that should be avoided whenever possible. Consider to use arrays instead.

12
  • 34
    FYI, you cannot partially use a variable. eg. $my_obj = Package\$class_name();. Instead you have to $class_name = "Package\\" . $class_name; $my_obj = new $class_name();
    – Birla
    Jul 10, 2014 at 16:58
  • 16
    Please note the when using namespaces, you must supply the full path: $className = '\Foo\Bar\MyClass'; $instance = new $className(); Dec 16, 2014 at 8:23
  • 6
    There is no spoon...only php. May 17, 2016 at 13:47
  • 6
    but one question. The method described above can be used to create a new class instance. What if I want to statically call a method of an existing class ? I tried as follows: $model = $user_model::find()->All(); where $user_model is the variable containing the string of the class being called Jun 23, 2016 at 13:30
  • 1
    Since we're dealing with strings, it's safer to escape the backslashes: $className = '\\Foo\\Bar\\MyClass'; … right? Jul 10, 2019 at 14:56
29

You can simply use the following syntax to create a new class (this is handy if you're creating a factory):

$className = $whatever;
$object = new $className;

As an (exceptionally crude) example factory method:

public function &factory($className) {

    require_once($className . '.php');
    if(class_exists($className)) return new $className;

    die('Cannot create new "' . $className . '" class - includes not found or class unavailable.');
}
1
  • 1
    Don't you miss a dot between the class name and the extension?require_once($className.'php'); -> require_once($className.'.php');
    – J Quest
    Jun 18, 2018 at 16:26
15

have a look at example 3 from http://www.php.net/manual/en/language.oop5.basic.php

$className = 'Foo';
$instance = new $className(); // Foo()
10

Lets say ClassOne is defined as:

public class ClassOne
{
    protected $arg1;
    protected $arg2;

    //Contructor
    public function __construct($arg1, $arg2)
    {
        $this->arg1 = $arg1;
        $this->arg2 = $arg2;
    }

    public function echoArgOne
    {
        echo $this->arg1;
    }

}

Using PHP Reflection;

$str = "One";
$className = "Class".$str;
$class = new \ReflectionClass($className);

Create a new Instance:

$instance = $class->newInstanceArgs(["Banana", "Apple")]);

Call a method:

$instance->echoArgOne();
//prints "Banana"

Use a variable as a method:

$method = "echoArgOne";
$instance->$method();

//prints "Banana"

Using Reflection instead of just using the raw string to create an object gives you better control over your object and easier testability (PHPUnit relies heavily on Reflection)

1
  • Just for the curious, there is neglectable overhead in time for the using Reflection plus better control over exceptions like a missing class.
    – theking2
    Feb 22 at 8:38
2
// Way #1
$className = "App\MyClass";
$instance = new $className();

// Way #2
$className = "App\MyClass";
$class = new \ReflectionClass($className);

// Create a new Instance without arguments:
$instance = $class->newInstance();

// Create a new Instance with arguments (need a contructor):
$instance = $class->newInstanceArgs(["Banana", "Apple"]);
0

In case you have a namespace at the top of the file.

import the desired class at the top of the current file:

use \Foo\Bar\MyClass; 

// Assign the class namespace to a variable. 
$class = MyClass::class; 

// Create a new instance
$instance = new $class();

The ::class will return the entire namespace of the desired class

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.