Invocazione del metodo della classe dinamica in PHP


88

C'è un modo per invocare dinamicamente un metodo nella stessa classe per PHP? Non ho la sintassi corretta, ma sto cercando di fare qualcosa di simile a questo:

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

Era la domanda originale? Stavo cercando di invocare un metodo in modo dinamico e ho trovato questa domanda. È la stessa sintassi data da andy.gurin e non vedo un collegamento che mostri l'aggiornamento sulla domanda. Comunque ... Grazie per averlo chiesto e grazie ai contributori :-)
Luc M

5
@ Luc - Era la domanda originale. Si scopre che avevo la sintassi corretta quando ho chiesto, ma qualcos'altro era sbagliato nel mio codice, quindi non ha funzionato.
VirtuosiMedia

Risposte:


176

C'è più di un modo per farlo:

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

Puoi anche usare l'api di riflessione http://php.net/manual/en/class.reflection.php


Immagino che forse avevo la sintassi giusta, quindi qualcos'altro è sbagliato nel mio codice in quanto non funziona correttamente. Hmm ...
VirtuosiMedia il

Una parola per chi è stanco, se i tuoi metodi vengono chiamati su oggetti e testati con PHPUnit, call_user_func_arrayè quella che fa per te.
OK, certo

Amico mio, mi hai appena salvato la giornata! Stavo chiamando call_user_func_array($this->$name, ...)e mi chiedevo perché non avrebbe funzionato!
Pubudu Dodangoda

11

Basta omettere le parentesi graffe:

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

10

Puoi usare l'overloading in PHP: Overloading

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

Se stai lavorando all'interno di una classe in PHP, ti consiglio di utilizzare la funzione __call in sovraccarico in PHP5. Puoi trovare il riferimento qui .

Fondamentalmente __call fa per le funzioni dinamiche quello che __set e __get fanno per le variabili in OO PHP5.


2

Ancora valido dopo tutti questi anni! Assicurati di tagliare $ methodName se si tratta di contenuto definito dall'utente. Non sono riuscito a far funzionare $ this -> $ methodName finché non ho notato che aveva uno spazio iniziale.


Se si tratta di contenuto definito dall'utente, assicurati di fare molto di più che tagliare il nome! Come ... controllo di sicurezza! ;)
Erk

Da qualche parte su Internet, ho spiegato in dettaglio come convertire l'utente inserito utf8 in caratteri sicuri per Windows. QuickBooks mi ha analizzato questo strizzatore - e perché QB non fa più parte del modo in cui completo le vendite ...
Chris K

Consentite davvero al client di specificare un input, che chiama dinamicamente alcuni metodi?! Non ho parole
Mcsky

Ovviamente convalidato e verificato che la classe contenga effettivamente un tale metodo denominato. Esistono molti modi per verificare il valore. Batte una lunga dichiarazione di switch.
Snapey

1

Nel mio caso.

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

Utilizzando PHP SOAP.


2
Non ne sono sicuro, ma fai attenzione al problema di sicurezza
tom10271

1

È possibile memorizzare un metodo in una singola variabile utilizzando una chiusura:

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: ho modificato il codice e ora è compatibile con PHP 5.3. Un altro esempio qui

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.