Erstellen einer PHP-Klasseninstanz mit einer Zeichenfolge

223

Ich habe zwei Klassen class ClassOne { }und class ClassTwo {}. Ich bekomme eine Zeichenfolge, die entweder "One"oder sein kann "Two".

Anstatt eine lange switchAnweisung wie:

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

Gibt es eine Möglichkeit, eine Instanz mithilfe einer Zeichenfolge zu erstellen, z new Class("Class" . $str);.

Joel
quelle

Antworten:

484

Ja, du kannst!

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

Geben Sie bei Verwendung von Namespaces den vollständig qualifizierten Namen an :

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

Andere coole Sachen, die du in PHP machen kannst, sind:
Variable Variablen :

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

Und variable Funktionen und Methoden.

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

$method = 'doStuff';
$object = new MyClass();
$object->$method(); // calls the MyClass->doStuff() method. 
Bob Fanger
quelle
1
Danke für die Beispiele!
Joel
28
Zu Ihrer Information, Sie können eine Variable nicht teilweise verwenden. z.B. $my_obj = Package\$class_name();. Stattdessen müssen Sie$class_name = "Package\\" . $class_name; $my_obj = new $class_name();
Birla
14
Bitte beachten Sie, dass Sie bei der Verwendung von Namespaces den vollständigen Pfad $className = '\Foo\Bar\MyClass'; $instance = new $className();
angeben
5
Es gibt keinen Löffel ... nur PHP.
Kapitän Hypertext
4
aber eine Frage. Mit der oben beschriebenen Methode kann eine neue Klasseninstanz erstellt werden. Was ist, wenn ich eine Methode einer vorhandenen Klasse statisch aufrufen möchte? Ich habe Folgendes versucht: $model = $user_model::find()->All(); Wo $user_modelist die Variable, die den String der aufgerufenen Klasse enthält
Ramesh Pareek
22

Sie können einfach die folgende Syntax verwenden, um eine neue Klasse zu erstellen (dies ist praktisch, wenn Sie eine Factory erstellen ):

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

Als (außergewöhnlich grobe) Beispielfabrikmethode:

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
quelle
1
Verpassen Sie keinen Punkt zwischen dem Klassennamen und der Erweiterung? require_once($className.'php'); ->require_once($className.'.php');
J Quest
4

Nehmen wir an, es ClassOneist definiert als:

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

}

Verwenden von PHP Reflection;

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

Erstellen Sie eine neue Instanz:

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

Rufen Sie eine Methode auf:

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

Verwenden Sie eine Variable als Methode:

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

//prints "Banana"

Wenn Sie Reflection verwenden, anstatt nur die Rohzeichenfolge zum Erstellen eines Objekts zu verwenden, haben Sie eine bessere Kontrolle über Ihr Objekt und eine einfachere Testbarkeit (PHPUnit ist stark von Reflection abhängig).

Neu machen
quelle