Criando instância de classe PHP com uma sequência

223

Eu tenho duas aulas class ClassOne { }e class ClassTwo {}. Estou recebendo uma string que pode ser um "One"ou outro "Two".

Em vez de usar uma switchdeclaração longa , como:

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

Existe uma maneira de criar uma instância usando uma string, ou seja new Class("Class" . $str);?

Joel
fonte

Respostas:

484

Sim você pode!

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

Ao usar espaços para nome, forneça o nome completo :

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

Outras coisas legais que você pode fazer no php são:
Variáveis ​​variáveis :

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

E funções e métodos variáveis.

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

$method = 'doStuff';
$object = new MyClass();
$object->$method(); // calls the MyClass->doStuff() method. 
Bob Fanger
fonte
1
Obrigado pelos exemplos!
Joel
28
Para sua informação, você não pode usar parcialmente uma variável. por exemplo. $my_obj = Package\$class_name();. Em vez disso, você deve$class_name = "Package\\" . $class_name; $my_obj = new $class_name();
Birla
14
Observe que, ao usar espaços para nome, você deve fornecer o caminho completo:$className = '\Foo\Bar\MyClass'; $instance = new $className();
Giel Berkers
5
Não há colher ... apenas php.
Captain Hypertext
4
mas uma pergunta. O método descrito acima pode ser usado para criar uma nova instância de classe. E se eu quiser chamar estaticamente um método de uma classe existente? Eu tentei o seguinte: $model = $user_model::find()->All(); onde $user_modelé a variável que contém a string da classe que está sendo chamado
Ramesh Pareek
22

Você pode simplesmente usar a seguinte sintaxe para criar uma nova classe (isso é útil se você estiver criando uma fábrica ):

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

Como um exemplo de método de fábrica (excepcionalmente bruto):

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
fonte
1
Você não perde um ponto entre o nome da turma e a extensão? require_once($className.'php'); ->require_once($className.'.php');
J quest
4

Vamos dizer que ClassOneé definido 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);

Crie uma nova instância:

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

Chame um método:

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

Use uma variável como método:

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

//prints "Banana"

Usar o Reflection em vez de apenas usar a string não processada para criar um objeto oferece um controle melhor sobre o objeto e uma testabilidade mais fácil (o PHPUnit depende muito do Reflection)

Remade
fonte