Pemanggilan metode kelas dinamis dalam PHP

88

Apakah ada cara untuk secara dinamis memanggil metode di kelas yang sama untuk PHP? Saya tidak memiliki sintaks yang benar, tetapi saya ingin melakukan sesuatu yang mirip dengan ini:

$this->{$methodName}($arg1, $arg2, $arg3);
VirtuosiMedia
sumber
Apakah itu pertanyaan aslinya? Saya sedang mencari pemanggilan metode secara dinamis dan saya menemukan pertanyaan ini. Ini adalah sintaks yang sama yang diberikan oleh andy.gurin dan saya tidak melihat tautan yang menunjukkan pembaruan pada pertanyaan tersebut. Pokoknya ... Terima kasih telah bertanya dan terima kasih kepada kontributor :-)
Luc M
5
@ Luc - Itu adalah pertanyaan asli. Ternyata saya memiliki sintaks yang benar ketika saya bertanya, tetapi ada sesuatu yang salah dengan kode saya, jadi tidak berhasil.
VirtuosiMedia

Jawaban:

176

Ada lebih dari satu cara untuk melakukan itu:

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

Anda bahkan dapat menggunakan api refleksi http://php.net/manual/en/class.reflection.php

andy.gurin
sumber
Saya kira mungkin saya memiliki sintaks yang benar, jadi ada sesuatu yang salah dengan kode saya karena tidak berfungsi dengan benar. Hmm ...
VirtuosiMedia
Sebuah kata untuk lelah, jika metode Anda dipanggil pada objek dan diuji dengan PHPUnit, call_user_func_arrayadalah yang tepat untuk Anda.
Oke yakin
Kamu temanku, baru saja menyelamatkan hariku! Saya menelepon call_user_func_array($this->$name, ...)dan bertanya-tanya mengapa itu tidak berhasil!
Pubudu Dodangoda
11

Abaikan saja kawat gigi:

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

Anda dapat menggunakan Overloading di 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
RodolfoNeto
sumber
3

Anda juga bisa menggunakan call_user_func()dancall_user_func_array()

Peter Bailey
sumber
3

Jika Anda bekerja di dalam kelas di PHP, maka saya akan merekomendasikan menggunakan fungsi __call yang kelebihan beban di PHP5. Anda dapat menemukan referensinya di sini .

Pada dasarnya __call melakukan untuk fungsi dinamis apa yang dilakukan __set dan __get untuk variabel di OO PHP5.

Noah Goodrich
sumber
2

Masih berlaku setelah bertahun-tahun! Pastikan Anda memangkas $ methodName jika itu adalah konten yang ditentukan pengguna. Saya tidak bisa mendapatkan $ this -> $ methodName untuk bekerja sampai saya perhatikan itu memiliki spasi utama.

Snapey
sumber
Jika itu adalah konten yang ditentukan pengguna, pastikan Anda melakukan lebih dari sekadar memangkas namanya! Seperti ... pemeriksaan keamanan! ;)
Erk
Di suatu tempat di internet, saya merinci cara mengonversi pengguna yang memasukkan utf8 menjadi karakter yang aman untuk Windows. QuickBooks mengarahkan saya melalui pemeras itu - dan mengapa QB tidak lagi menjadi bagian dari cara saya menyelesaikan penjualan ...
Chris K
Apakah Anda benar-benar mengizinkan klien untuk menentukan input, yang memanggil beberapa metode secara dinamis?! Saya tidak punya kata
Mcsky
Jelas divalidasi dan diperiksa bahwa kelas sebenarnya berisi metode bernama seperti itu. Ada banyak cara untuk memeriksa nilainya. Ini mengalahkan pernyataan sakelar yang panjang.
Snapey
1

Dalam hal ini.

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

Menggunakan PHP SOAP.

pengguna46637
sumber
2
Saya tidak yakin tapi hati-hati tentang masalah keamanan
tom10271
1

Anda dapat menyimpan metode dalam satu variabel menggunakan closure:

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: Saya telah mengedit kode dan sekarang kompatibel dengan PHP 5.3. Contoh lain di sini

David
sumber