289

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

602

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.

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

12 Comments

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();
Please note the when using namespaces, you must supply the full path: $className = '\Foo\Bar\MyClass'; $instance = new $className();
There is no spoon...only php.
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
Since we're dealing with strings, it's safer to escape the backslashes: $className = '\\Foo\\Bar\\MyClass'; … right?
|
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 Comment

Don't you miss a dot between the class name and the extension?require_once($className.'php'); -> require_once($className.'.php');
15

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

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

Comments

12

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 Comment

Just for the curious, there is neglectable overhead in time for the using Reflection plus better control over exceptions like a missing class.
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"]);

Comments

1

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

Comments

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.