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);

¿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


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


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


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.


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.


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.


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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.