Création d'une instance de classe PHP avec une chaîne

223

J'ai deux classes, class ClassOne { }et class ClassTwo {}. Je reçois une chaîne qui peut être soit "One"ou "Two".

Au lieu d'utiliser une longue switchdéclaration telle que:

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

Existe-t-il un moyen de créer une instance à l'aide d'une chaîne, c'est new Class("Class" . $str);-à- dire ?

Joel
la source

Réponses:

484

Oui, vous pouvez!

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

Lorsque vous utilisez des espaces de noms, indiquez le nom complet :

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

D'autres choses intéressantes que vous pouvez faire en php sont:
Variables variables :

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

Et des fonctions et méthodes variables.

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

$method = 'doStuff';
$object = new MyClass();
$object->$method(); // calls the MyClass->doStuff() method. 
Bob Fanger
la source
1
Merci pour les exemples!
Joel
28
Pour info, vous ne pouvez pas utiliser partiellement une variable. par exemple. $my_obj = Package\$class_name();. Au lieu de cela, vous devez$class_name = "Package\\" . $class_name; $my_obj = new $class_name();
Birla
14
Veuillez noter que lorsque vous utilisez des espaces de noms, vous devez fournir le chemin complet:$className = '\Foo\Bar\MyClass'; $instance = new $className();
Giel Berkers
5
Il n'y a pas de cuillère ... seulement du php.
Captain Hypertext
4
mais une question. La méthode décrite ci-dessus peut être utilisée pour créer une nouvelle instance de classe. Que faire si je veux appeler statiquement une méthode d'une classe existante? J'ai essayé comme suit: $model = $user_model::find()->All(); $user_modelest la variable contenant la chaîne de la classe appelée
Ramesh Pareek
22

Vous pouvez simplement utiliser la syntaxe suivante pour créer une nouvelle classe (c'est pratique si vous créez une usine ):

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

Comme exemple (exceptionnellement grossier) de méthode d'usine:

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
la source
1
Ne manquez-vous pas un point entre le nom de la classe et l'extension? require_once($className.'php'); ->require_once($className.'.php');
J Quest
4

Disons que ClassOnese définit comme:

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

}

Utilisation de PHP Reflection;

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

Créez une nouvelle instance:

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

Appelez une méthode:

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

Utilisez une variable comme méthode:

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

//prints "Banana"

Utiliser Reflection au lieu d'utiliser simplement la chaîne brute pour créer un objet vous donne un meilleur contrôle sur votre objet et une testabilité plus facile (PHPUnit s'appuie fortement sur Reflection)

Refait
la source