Invocación de método de clase dinámica en PHP

88

¿Hay alguna forma de invocar dinámicamente un método en la misma clase para PHP? No tengo la sintaxis correcta, pero estoy buscando hacer algo similar a esto:

$this->{$methodName}($arg1, $arg2, $arg3);
VirtuosiMedia
fuente
¿Fue la pregunta original? Estaba buscando invocar un método dinámicamente y encontré esta pregunta. Es la misma sintaxis dada por andy.gurin y no veo un enlace que muestre la actualización de la pregunta. De todos modos ... Gracias por haber preguntado y gracias a los contribuyentes :-)
Luc M
5
@Luc - Era la pregunta original. Resulta que tenía la sintaxis correcta cuando pregunté, pero había algo más mal en mi código, por lo que no funcionó.
VirtuosiMedia

Respuestas:

176

Hay más de una forma de hacerlo:

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

Incluso puede usar la API de reflexión http://php.net/manual/en/class.reflection.php

andy.gurin
fuente
Supongo que tal vez tenía la sintaxis correcta, así que algo más está mal con mi código ya que no funciona correctamente. Hmm ...
VirtuosiMedia
Una palabra para los cansados, si sus métodos se invocan en objetos y se prueban con PHPUnit, call_user_func_arrayes el indicado para usted.
acuerdo, seguro
¡Tú, amigo mío, me acabas de salvar el día! ¡Estaba llamando call_user_func_array($this->$name, ...)y me preguntaba por qué no funcionaría!
Pubudu Dodangoda
11

Simplemente omita las llaves:

$this->$methodName($arg1, $arg2, $arg3);
Konrad Rudolph
fuente
10

Puede utilizar la sobrecarga en PHP: sobrecarga

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
RodolfoNeto
fuente
3

También puede utilizar call_user_func()ycall_user_func_array()

Peter Bailey
fuente
3

Si está trabajando dentro de una clase en PHP, le recomendaría usar la función __call sobrecargada en PHP5. Puede encontrar la referencia aquí .

Básicamente, __call hace para las funciones dinámicas lo que __set y __get hacen para las variables en OO PHP5.

Noah Goodrich
fuente
2

¡Sigue siendo válido después de todos estos años! Asegúrese de recortar $ methodName si es contenido definido por el usuario. No pude hacer que $ this -> $ methodName funcionara hasta que noté que tenía un espacio inicial.

Snapey
fuente
Si se trata de contenido definido por el usuario, asegúrese de hacer mucho más que recortar el nombre. Como ... ¡compruébalo! ;)
Erk
En algún lugar de Internet, detallé cómo convertir utf8 ingresado por el usuario en caracteres seguros para Windows. QuickBooks Me corrió a través de ese escurridor - y por qué QB ya no es parte de la forma I de ventas completas ...
Chris K
¿Realmente está permitiendo que el cliente especifique una entrada que llame dinámicamente a algunos métodos? No tengo palabras
Mcsky
Obviamente validado y verificado que la clase realmente contiene un método con ese nombre. Hay muchas formas de comprobar el valor. Es mejor que una declaración de cambio larga.
Snapey
1

En mi caso.

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

Usando PHP SOAP.

user46637
fuente
2
No estoy seguro, pero tenga cuidado con el problema de seguridad
tom10271
1

Puede almacenar un método en una sola variable usando un cierre:

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"

EDITAR: He editado el código y ahora es compatible con PHP 5.3. Otro ejemplo aqui

David
fuente