creare un'istanza di una classe da una variabile in PHP?


146

So che questa domanda sembra piuttosto vaga, quindi renderò più chiaro con un esempio:

$var = 'bar';
$bar = new {$var}Class('var for __construct()'); //$bar = new barClass('var for __construct()');

Questo è quello che voglio fare. Come lo faresti? Potrei ovviamente usare eval () in questo modo:

$var = 'bar';
eval('$bar = new '.$var.'Class(\'var for __construct()\');');

Ma preferirei stare lontano da eval (). C'è un modo per farlo senza eval ()?

Risposte:


215

Inserisci prima il nome classe in una variabile:

$classname=$var.'Class';

$bar=new $classname("xyz");

Questo è spesso il genere di cose che vedrai avvolto in un modello Factory.

Vedi Spazi dei nomi e funzionalità del linguaggio dinamico per ulteriori dettagli.


2
Questo è come lo faccio. Nota che all'interno delle classi puoi usare genitore e sé.
Ross,

1
Su una nota simile, puoi anche fare $ var = 'Nome'; $ obj -> { 'ottenere' $ var.} ();
Mario,

1
Un buon punto, tuttavia, funziona solo per le chiamate di metodo e non per i costruttori
Paul Dixon,

12
Se lavori con lo spazio dei nomi, inserisci lo spazio dei nomi corrente nella stringa:$var = __NAMESPACE__ . '\\' . $var . 'Class';
bastey

@bastey - ma perché? Ho appena trascorso troppo tempo a capire, perché questo non funzionerebbe senza lo spazio dei nomi che precede il nome della classe ...
jkulak,

72

Se usi gli spazi dei nomi

Nelle mie scoperte, penso che sia bello ricordare che tu (per quanto posso dire) devi dichiarare il percorso completo dello spazio dei nomi di una classe.

MyClass.php

namespace com\company\lib;
class MyClass {
}

index.php

namespace com\company\lib;

//Works fine
$i = new MyClass();

$cname = 'MyClass';

//Errors
//$i = new $cname;

//Works fine
$cname = "com\\company\\lib\\".$cname;
$i = new $cname;

6
L'unica soluzione funzionante quando è necessario creare con namespace, sono le tue. Grazie per la condivisione!
Tiago Gouvêa,

Ma questo è solo strano, perché non dovrebbe usare lo spazio dei nomi dichiarato?
Yisrael Dov il

@YisraelDov Sì, è decisamente contro intuitivo. Ma per qualsiasi motivo si comporti stranamente in questo contesto. Grazie php
csga5000,

@YisraelDov Immagino sia perché in quel caso creare un'istanza di una classe da un altro spazio dei nomi sarebbe un grosso mal di testa. Considera anche che le variabili possono essere passate in giro. Quando il nome della classe è scritto come testo in un file php, chiunque lo scriva sa esattamente in quale spazio dei nomi è scritto. Ma quando si passa una variabile tra le funzioni, sarebbe un incubo seguirlo. Inoltre, se usi get_class () restituirà il nome della classe FQ, in modo che possa essere archiviato immediatamente in una variabile e utilizzato ovunque. Se dipendesse dallo spazio dei nomi del file, non funzionerebbe molto bene.
sbnc.eu,

61

Come passare anche i parametri dinamici del costruttore

Se si desidera passare i parametri del costruttore dinamico alla classe, è possibile utilizzare questo codice:

$reflectionClass = new ReflectionClass($className);

$module = $reflectionClass->newInstanceArgs($arrayOfConstructorParameters);

Ulteriori informazioni su classi e parametri dinamici

PHP> = 5.6

A partire da PHP 5.6 puoi semplificarlo ancora di più usando Argument Unpacking :

// The "..." is part of the language and indicates an argument array to unpack.
$module = new $className(...$arrayOfConstructorParameters);

Grazie a DisgruntledGoat per averlo sottolineato.


7
Da PHP 5.6 dovresti essere in grado di usare l'argomento disimballaggio:new $className(...$params)
DisgruntledGoat

29
class Test {
    public function yo() {
        return 'yoes';
    }
}

$var = 'Test';

$obj = new $var();
echo $obj->yo(); //yoes

No, non è un buon esempio. Funziona solo se tutto è nello stesso file php.
fralbo,

2
2ndGAB dovrebbe rimuovere questo commento. Il caricamento automatico non ha nulla a che fare con questa domanda.
Jim Maguire,

-1

Consiglierei i metodi call_user_func()o call_user_func_arrayphp. Puoi verificarli qui ( call_user_func_array , call_user_func ).

esempio

class Foo {
static public function test() {
    print "Hello world!\n";
}
}

 call_user_func('Foo::test');//FOO is the class, test is the method both separated by ::
 //or
 call_user_func(array('Foo', 'test'));//alternatively you can pass the class and method as an array

Se hai argomenti che stai passando al metodo, usa la call_user_func_array()funzione.

esempio.

class foo {
function bar($arg, $arg2) {
    echo __METHOD__, " got $arg and $arg2\n";
}
}

// Call the $foo->bar() method with 2 arguments
call_user_func_array(array("foo", "bar"), array("three", "four"));
//or
//FOO is the class, bar is the method both separated by ::
call_user_func_array("foo::bar"), array("three", "four"));

3
Questa risposta non si applica alla domanda. OP sta chiedendo come ISTANTIRE una classe (innescando la classe __costruisci il metodo in modo dinamico) da una stringa variabile e riportando l'OGGETTO CLASSE in una nuova variabile - il tuo consiglio restituirà il VALORE del metodo class-> ([]) tu ' chiamando, non l'oggetto di classe, quindi non si applica per questo caso. Vedere il valore di ritorno php.net/manual/en/function.call-user-func-array.php
ChrisN
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.