utworzyć instancję klasy ze zmiennej w PHP?


146

Wiem, że to pytanie brzmi dość niejasno, więc wyjaśnię je na przykładzie:

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

To jest to, co chcę zrobić. Jak byś to zrobił? Oczywiście mógłbym użyć eval () w ten sposób:

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

Ale wolałbym trzymać się z dala od eval (). Czy można to zrobić bez eval ()?

Odpowiedzi:


214

Najpierw umieść nazwę klasy w zmiennej:

$classname=$var.'Class';

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

Często jest to coś, co można zobaczyć w formie fabrycznej.

Aby uzyskać więcej informacji, zobacz Przestrzenie nazw i funkcje języka dynamicznego .


2
Tak to robię. Zauważ, że w ramach zajęć możesz używać rodzica i siebie.
— Ross

1
Podobnie możesz zrobić $ var = 'Name'; $ obj -> {'get'. $ var} ();
— Mario

1
Dobra uwaga, chociaż działa to tylko dla wywołań metod, a nie konstruktorów
— Paul Dixon,

12
Jeśli pracujesz z przestrzenią nazw, umieść bieżącą przestrzeń nazw w ciągu:$var = __NAMESPACE__ . '\\' . $var . 'Class';
— bastey

@bastey - ale dlaczego? Po prostu spędziłem zbyt dużo czasu na zastanawianiu się, dlaczego to nie zadziała bez przestrzeni nazw poprzedzającej nazwę klasy ...
— jkulak

72

Jeśli używasz przestrzeni nazw

W moich własnych ustaleniach myślę, że dobrze jest wspomnieć, że (o ile wiem) musisz zadeklarować pełną ścieżkę przestrzeni nazw klasy.

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
Jedynym działającym rozwiązaniem, gdy trzeba tworzyć z przestrzenią nazw, są Twoje. Dziękuję za udostępnienie!
— Tiago Gouvêa

Ale to jest po prostu dziwne, dlaczego nie miałoby używać zadeklarowanej przestrzeni nazw?
— Yisrael Dov

@YisraelDov Tak, jest to zdecydowanie sprzeczne z intuicją. Ale z jakiegoś powodu zachowuje się dziwnie w tym kontekście. Dzięki php
— csga5000

@YisraelDov Wydaje mi się, że dzieje się tak dlatego, że w takim przypadku utworzenie instancji klasy z innej przestrzeni nazw byłoby ogromnym bólem głowy. Weź również pod uwagę, że zmienne mogą być przekazywane. Kiedy nazwa klasy jest zapisywana jako tekst w pliku php, ktokolwiek ją zapisze, wie dokładnie, w jakiej przestrzeni nazw jest zapisana. Ale kiedy zmienna jest przekazywana między funkcjami, śledzenie jej byłoby koszmarem. Ponadto, jeśli użyjesz get_class (), zwróci ona nazwę klasy FQ, dzięki czemu można ją od razu przechowywać w zmiennej i używać w dowolnym miejscu. Gdyby zależało to od przestrzeni nazw pliku, nie działałoby to zbyt dobrze.
— sbnc.eu

61

Jak również przekazywać parametry konstruktora dynamicznego

Jeśli chcesz przekazać do klasy parametry konstruktora dynamicznego, możesz użyć tego kodu:

$reflectionClass = new ReflectionClass($className);

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

Więcej informacji o klasach i parametrach dynamicznych

PHP> = 5.6

Od PHP 5.6 możesz to jeszcze bardziej uprościć używając Rozpakowywanie argumentów :

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

Dziękuję DisgruntledGoat za wskazanie tego.


7
Od PHP 5.6 powinno być możliwe rozpakowywanie argumentów:new $className(...$params)
— DisgruntledGoat

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

$var = 'Test';

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

Nie, nie jest to dobry przykład. Działa tylko wtedy, gdy wszystko jest w tym samym pliku php.
— fralbo

2
2ndGAB powinien usunąć ten komentarz. Automatyczne ładowanie nie ma nic wspólnego z tym pytaniem.
— Jim Maguire

-1

Chciałbym polecić call_user_func()lub call_user_func_arrayphp metod. Możesz je sprawdzić tutaj ( call_user_func_array , call_user_func ).

przykład

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

Jeśli masz argumenty, które przekazujesz do metody, użyj call_user_func_array()funkcji.

przykład.

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
Ta odpowiedź nie dotyczy pytania. OP pyta, jak NATYCHMIASTOWAĆ klasę (dynamicznie wyzwalając metodę class __construct) z ciągu zmiennej i otrzymując OBIEKT KLASY z powrotem w nowej zmiennej - twoja rada zwróci WARTOŚĆ klasy-> metoda ([]) ty ' ponowne wywołanie, a nie obiekt klasy, więc nie ma zastosowania w tym przypadku. Zobacz wartość zwracaną php.net/manual/en/function.call-user-func-array.php
— ChrisN
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.