Dynamiczne wywołanie metod klas w PHP


88

Czy istnieje sposób na dynamiczne wywołanie metody w tej samej klasie dla PHP? Nie mam prawidłowej składni, ale chcę zrobić coś podobnego do tego:

$this->{$methodName}($arg1, $arg2, $arg3);

Czy to było pierwotne pytanie? Szukałem dynamicznego wywoływania metody i znalazłem to pytanie. To ta sama składnia, którą podał andy.gurin i nie widzę linku, który pokazuje aktualizację pytania. W każdym razie ... Dzięki, że poprosiłem i dziękuję współpracownikom :-)
Luc M

5
@Luc - To było oryginalne pytanie. Okazuje się, że składnia była poprawna, gdy zapytałem, ale coś innego było nie tak z moim kodem, więc nie zadziałało.
VirtuosiMedia

Odpowiedzi:


176

Jest na to więcej niż jeden sposób:

$this->{$methodName}($arg1, $arg2, $arg3);
$this->$methodName($arg1, $arg2, $arg3);
call_user_func_array(array($this, $methodName), array($arg1, $arg2, $arg3));

Możesz nawet użyć odbicia api http://php.net/manual/en/class.reflection.php


Myślę, że może miałem poprawną składnię, więc coś innego jest nie tak z moim kodem, ponieważ nie działa on całkiem poprawnie. Hmm ...
VirtuosiMedia

Słowo dla zmęczonego, jeśli twoje metody są wywoływane na obiektach i testowane za pomocą PHPUnit, call_user_func_arrayjest dla ciebie.
OK,

Ty mój przyjacielu, właśnie uratowałeś mi dzień! Dzwoniłem call_user_func_array($this->$name, ...)i zastanawiałem się, dlaczego to nie zadziała!
Pubudu Dodangoda


10

Możesz użyć Overloading in PHP: Overloading

class Test {

    private $name;

    public function __call($name, $arguments) {
        echo 'Method Name:' . $name . ' Arguments:' . implode(',', $arguments);
        //do a get
        if (preg_match('/^get_(.+)/', $name, $matches)) {
            $var_name = $matches[1];
            return $this->$var_name ? $this->$var_name : $arguments[0];
        }
        //do a set
        if (preg_match('/^set_(.+)/', $name, $matches)) {
            $var_name = $matches[1];
            $this->$var_name = $arguments[0];
        }
    }
}

$obj = new Test();
$obj->set_name('Any String'); //Echo:Method Name: set_name Arguments:Any String
echo $obj->get_name();//Echo:Method Name: get_name Arguments:
                      //return: Any String


3

Jeśli pracujesz w klasie w PHP, polecam użycie przeciążonej funkcji __call w PHP5. Możesz znaleźć odniesienie tutaj .

Zasadniczo __call robi dla funkcji dynamicznych to, co __set i __get robi dla zmiennych w OO PHP5.


2

Nadal ważne po tylu latach! Upewnij się, że przycinasz $ methodName, jeśli jest to zawartość zdefiniowana przez użytkownika. Nie mogłem zmusić $ this -> $ methodName do działania, dopóki nie zauważyłem, że ma wiodącą spację.


Jeśli jest to treść zdefiniowana przez użytkownika, upewnij się, że robisz znacznie więcej niż tylko przycinanie nazwy! Na przykład ... sprawdź bezpieczeństwo! ;)
Erk

Gdzieś w Internecie szczegółowo opisałem, jak przekonwertować wprowadzone przez użytkownika utf8 na znaki bezpieczne dla systemu Windows. QuickBooks przeprowadził mnie przez tę wyżymaczkę - i dlaczego QB nie jest już częścią sposobu, w jaki kończę sprzedaż ...
Chris K,

Czy naprawdę pozwalasz klientowi określić dane wejściowe, które dynamicznie wywołują niektóre metody? Brak mi słów
Mcsky

Oczywiście zweryfikowano i sprawdzono, czy klasa faktycznie zawiera taką nazwaną metodę. Istnieje wiele sposobów sprawdzenia wartości. To bije długie oświadczenie dotyczące przełącznika.
Snapey

1

W moim przypadku.

$response = $client->{$this->requestFunc}($this->requestMsg);

Korzystanie z PHP SOAP.


2
Nie jestem pewien, ale uważaj na kwestię bezpieczeństwa
tom10271

1

Możesz przechowywać metodę w jednej zmiennej za pomocą zamknięcia:

class test{        

    function echo_this($text){
        echo $text;
    }

    function get_method($method){
        $object = $this;
        return function() use($object, $method){
            $args = func_get_args();
            return call_user_func_array(array($object, $method), $args);           
        };
    }
}

$test = new test();
$echo = $test->get_method('echo_this');
$echo('Hello');  //Output is "Hello"

EDYCJA: wyedytowałem kod i teraz jest kompatybilny z PHP 5.3. Tutaj kolejny przykład

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.