Invocation de méthode de classe dynamique en PHP

88

Existe-t-il un moyen d'invoquer dynamiquement une méthode de la même classe pour PHP? Je n'ai pas la bonne syntaxe, mais je cherche à faire quelque chose de similaire à ceci:

$this->{$methodName}($arg1, $arg2, $arg3);
VirtuosiMedia
la source
Était-ce la question initiale? Je cherchais à invoquer dynamiquement une méthode et j'ai trouvé cette question. C'est la même syntaxe que celle donnée par andy.gurin et je ne vois pas de lien qui montre la mise à jour de la question. En tout cas ... Merci d'avoir posé la question et merci aux contributeurs :-)
Luc M
5
@Luc - C'était la question initiale. Il s'avère que j'avais la syntaxe correcte lorsque j'ai demandé, mais quelque chose d'autre n'allait pas avec mon code, donc cela n'a pas fonctionné.
VirtuosiMedia

Réponses:

176

Il y a plus d'une façon de faire cela:

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

Vous pouvez même utiliser l'API de réflexion http://php.net/manual/en/class.reflection.php

andy.gurin
la source
Je suppose que j'avais peut-être la syntaxe correcte, donc quelque chose d'autre ne va pas avec mon code car il ne fonctionne pas tout à fait correctement. Hmm ...
VirtuosiMedia
Un mot aux fatigués, si vos méthodes sont appelées sur des objets et testées avec PHPUnit, call_user_func_arrayc'est celui qu'il vous faut.
OK sûr
Toi mon ami, viens de sauver ma journée! J'appelais call_user_func_array($this->$name, ...)et je me demandais pourquoi cela ne marcherait pas!
Pubudu Dodangoda
11

Omettez simplement les accolades:

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

Vous pouvez utiliser la surcharge en PHP: surcharge

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
la source
3

Vous pouvez également utiliser call_user_func()etcall_user_func_array()

Peter Bailey
la source
3

Si vous travaillez dans une classe en PHP, je vous recommande d'utiliser la fonction __call surchargée en PHP5. Vous pouvez trouver la référence ici .

Fondamentalement, __call fait pour les fonctions dynamiques ce que __set et __get font pour les variables dans OO PHP5.

Noah Goodrich
la source
2

Toujours valable après toutes ces années! Assurez-vous de découper $ methodName s'il s'agit d'un contenu défini par l'utilisateur. Je ne pouvais pas faire fonctionner $ this -> $ methodName jusqu'à ce que je remarque qu'il y avait un espace au début.

Snapey
la source
S'il s'agit d'un contenu défini par l'utilisateur, assurez-vous de faire bien plus que simplement couper le nom! Tels que ... vérifiez la sécurité! ;)
Erk
Quelque part sur Internet, j'ai détaillé comment convertir l'utilisateur entré utf8 en caractères sûrs pour Windows. QuickBooks m'a expliqué cette essoreuse - et pourquoi QB ne fait plus partie de la façon dont je réalise les ventes ...
Chris K
Autorisez-vous vraiment le client à spécifier une entrée, qui appelle dynamiquement certaines méthodes?! Je n'ai pas de mots
Mcsky
Évidemment validé et vérifié que la classe contient effectivement une telle méthode nommée. Il existe de nombreuses façons de vérifier la valeur. Il bat une longue déclaration de commutation.
Snapey
1

Dans mon cas.

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

Utilisation de PHP SOAP.

user46637
la source
2
Je ne suis pas sûr mais
faites
1

Vous pouvez stocker une méthode dans une seule variable à l'aide d'une fermeture:

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: J'ai édité le code et maintenant il est compatible avec PHP 5.3. Un autre exemple ici

David
la source