Виклик динамічного методу класу в PHP


88

Чи є спосіб динамічно викликати метод у тому ж класі для PHP? Я не маю правильного синтаксису, але я хочу зробити щось подібне до цього:

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

Це було оригінальне запитання? Я шукав, щоб динамічно викликати метод, і знайшов це питання. Це <той самий синтаксис, який надає andy.gurin, і я не бачу посилання, яке відображає оновлення щодо питання. У будь-якому випадку ... Дякую, що попросив і дякую авторам :-)
Люк М

5
@Luc - Це було оригінальне питання. Виявляється, синтаксис у мене був правильний, коли я запитував, але щось інше не було з моїм кодом, тому він не спрацював.
VirtuosiMedia

Відповіді:


176

Існує кілька способів зробити це:

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

Ви навіть можете використовувати API відображення http://php.net/manual/en/class.reflection.php


Я думаю, можливо, у мене був правильний синтаксис, тому щось інше не так з моїм кодом, оскільки він працює не зовсім правильно. Хм ...
VirtuosiMedia

Слово для втомлених, якщо ваші методи викликаються на об'єктах і тестуються за допомогою PHPUnit, call_user_func_array- це саме для вас.
Добре, звичайно

Ти мій друже, щойно врятував мій день! Я дзвонив call_user_func_array($this->$name, ...)і дивувався, чому це не спрацює!
Pubudu Dodangoda


10

Ви можете використовувати Перевантаження в PHP: Перевантаження

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

Якщо ви працюєте в класі в PHP, я б рекомендував використовувати перевантажену функцію __call у PHP5. Ви можете знайти посилання тут .

В основному __call робить для динамічних функцій те, що __set і __get роблять для змінних в OO PHP5.


2

Все ще діє після всіх цих років! Переконайтеся, що ви обрізали $ methodName, якщо це вміст, визначений користувачем. Я не міг отримати $ this -> $ methodName для роботи, поки не помітив, що він має провідний пробіл.


Якщо це користувацький вміст, переконайтеся, що ви робите набагато більше, ніж просто обрізаєте ім’я! Такі як ... перевірити безпеку! ;)
Ерк

Десь в Інтернеті я детально описав, як перетворити введеного користувача utf8 на символи, безпечні для Windows. QuickBooks провів мене через цей віджимач - і чому QB більше не є частиною того, як я закінчую продажі ...
Кріс К,

Ви дійсно дозволяєте клієнту вказати вхідні дані, які динамічно викликають деякі методи?! У мене немає слів
Mcsky,

Очевидно, перевірено та перевірено, що клас насправді містить такий названий метод. Існує багато способів перевірити вартість. Це перевершує довгий оператор перемикання.
Снейпі,

1

У моєму випадку.

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

Використання PHP SOAP.


2
Я не впевнений, але будь обережним щодо питання безпеки
tom10271 02

1

Ви можете зберігати метод в одній змінній, використовуючи закриття:

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"

EDIT: Я відредагував код, і тепер він сумісний з PHP 5.3. Ще один приклад тут

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.