Crear instancia de clase PHP con una cadena

223

Tengo dos clases class ClassOne { } y class ClassTwo {}. Estoy obteniendo una cadena que puede ser "One"o "Two".

En lugar de usar un largo switch declaración como:

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

¿Hay alguna manera de crear una instancia con una cadena, es decir? new Class("Class" . $str); ?

Joel
fuente

Respuestas:

484

¡Sí tu puedes!

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

Cuando use espacios de nombres, proporcione el nombre completo :

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

Otras cosas interesantes que puedes hacer en php son:
Variables variables :

$personCount = 123;
$varname = 'personCount';
echo $$varname; // echo's 123

Y funciones y métodos variables.

$func = 'my_function';
$func('param1'); // calls my_function('param1');

$method = 'doStuff';
$object = new MyClass();
$object->$method(); // calls the MyClass->doStuff() method. 
Bob Fanger
fuente
1
Gracias por los ejemplos!
Joel
28
Para su información, no puede usar parcialmente una variable. p.ej. $my_obj = Package\$class_name();. En cambio, tienes que$class_name = "Package\\" . $class_name; $my_obj = new $class_name();
Birla
14
Tenga en cuenta que cuando utilice espacios de nombres, debe proporcionar la ruta completa:$className = '\Foo\Bar\MyClass'; $instance = new $className();
Giel Berkers
55
No hay cuchara ... solo php.
Capitán Hipertexto
44
Pero una pregunta. El método descrito anteriormente se puede usar para crear una nueva instancia de clase. ¿Qué sucede si quiero llamar estáticamente a un método de una clase existente? Intenté lo siguiente: ¿ $model = $user_model::find()->All(); dónde se $user_modelllama la variable que contiene la cadena de la clase
Ramesh Pareek
22

Simplemente puede usar la siguiente sintaxis para crear una nueva clase (esto es útil si está creando una fábrica ):

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

Como un método de fábrica de ejemplo (excepcionalmente crudo):

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.');
}
John Parker
fuente
1
¿No te pierdes un punto entre el nombre de la clase y la extensión? require_once($className.'php'); ->require_once($className.'.php');
J Quest
4

Digamos que ClassOnese define como:

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;
    }

}

Usando PHP Reflection;

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

Crear una nueva instancia:

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

Llamar a un método:

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

Use una variable como método:

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

//prints "Banana"

El uso de Reflection en lugar de solo usar la cadena sin formato para crear un objeto le brinda un mejor control sobre su objeto y una capacidad de prueba más fácil (PHPUnit depende en gran medida de Reflection)

Rehecho
fuente