Dynamischer Klassenmethodenaufruf in PHP

85

Gibt es eine Möglichkeit, eine Methode in derselben Klasse für PHP dynamisch aufzurufen? Ich habe nicht die richtige Syntax, aber ich möchte etwas Ähnliches tun:

$this->{$methodName}($arg1, $arg2, $arg3);
VirtuosiMedia
quelle
War es die ursprüngliche Frage? Ich wollte eine Methode dynamisch aufrufen und fand diese Frage. Es ist dieselbe Syntax wie bei andy.gurin und ich sehe keinen Link, der das Update der Frage anzeigt. Wie auch immer ... Danke gefragt zu haben und danke an die Mitwirkenden :-)
Luc M
5
@ Luc - Es war die ursprüngliche Frage. Es stellte sich heraus, dass ich die richtige Syntax hatte, als ich fragte, aber etwas anderes stimmte nicht mit meinem Code, so dass es nicht funktionierte.
VirtuosiMedia

Antworten:

172

Es gibt mehr als einen Weg, dies zu tun:

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

Sie können sogar die Reflection-API http://php.net/manual/en/class.reflection.php verwenden

andy.gurin
quelle
Ich denke, vielleicht hatte ich die richtige Syntax, also stimmt etwas anderes mit meinem Code nicht, da er nicht ganz richtig funktioniert. Hmm ...
VirtuosiMedia
Ein Wort an die Müden, wenn Ihre Methoden für Objekte aufgerufen und mit PHPUnit getestet werden, call_user_func_arrayist das Richtige für Sie.
OK sicher
Du mein Freund, hast gerade meinen Tag gerettet! Ich rief an call_user_func_array($this->$name, ...)und fragte mich , warum es nicht funktionieren würde!
Pubudu Dodangoda
11

Lassen Sie einfach die Klammern weg:

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

Sie können das Überladen in PHP verwenden: Überladen

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
quelle
3

Sie können auch call_user_func()und verwendencall_user_func_array()

Peter Bailey
quelle
3

Wenn Sie in einer Klasse in PHP arbeiten, würde ich empfehlen, die überladene __call-Funktion in PHP5 zu verwenden. Die Referenz finden Sie hier .

Grundsätzlich macht __call für dynamische Funktionen das, was __set und __get für Variablen in OO PHP5 tun.

Noah Goodrich
quelle
2

Nach all den Jahren immer noch gültig! Stellen Sie sicher, dass Sie $ methodName kürzen, wenn es sich um benutzerdefinierten Inhalt handelt. Ich konnte $ this -> $ methodName nicht zum Laufen bringen, bis ich bemerkte, dass es ein führendes Leerzeichen hatte.

Snapey
quelle
Wenn es sich um benutzerdefinierten Inhalt handelt, stellen Sie sicher, dass Sie viel mehr tun, als nur den Namen zu kürzen! Wie ... Sicherheitskontrolle! ;)
Erk
Irgendwo im Internet habe ich detailliert beschrieben, wie der vom Benutzer eingegebene utf8 in Windows-sichere Zeichen konvertiert wird. QuickBooks hat mich durch diesen Wringer geführt - und warum QB nicht mehr dazu beiträgt, wie ich Verkäufe abschließe ...
Chris K
Erlauben Sie dem Client wirklich, eine Eingabe anzugeben, die einige Methoden dynamisch aufruft ?! Ich habe keine Worte
Mcsky
Offensichtlich validiert und überprüft, dass die Klasse tatsächlich eine solche benannte Methode enthält. Es gibt viele Möglichkeiten, den Wert zu überprüfen. Es schlägt eine lange switch-Anweisung.
Snapey
1

In meinem Fall.

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

Verwenden von PHP SOAP.

user46637
quelle
2
Ich bin nicht sicher, aber seien Sie vorsichtig mit Sicherheitsproblemen
tom10271
1

Sie können eine Methode mithilfe eines Abschlusses in einer einzelnen Variablen speichern:

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"

BEARBEITEN: Ich habe den Code bearbeitet und jetzt ist er mit PHP 5.3 kompatibel. Ein weiteres Beispiel hier

David
quelle