PHP'de dinamik sınıf yöntemi çağrısı


88

PHP için aynı sınıftaki bir yöntemi dinamik olarak çağırmanın bir yolu var mı? Sözdizimim doğru değil ama buna benzer bir şey yapmak istiyorum:

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

Orijinal soru muydu? Dinamik olarak bir yöntemi çağırmak istiyordum ve bu soruyu buldum. Andy.gurin tarafından verilen sözdizimiyle aynı ve soruyla ilgili güncellemeyi gösteren bir bağlantı görmüyorum. Her neyse ... Sorduğun ve katkıda bulunanlara teşekkürler :-)
Luc M

5
@Luc - Asıl soruydu. Görünüşe göre sorduğumda doğru sözdizimi vardı, ancak kodumda başka bir şey yanlıştı, bu yüzden işe yaramadı.
VirtuosiMedia

Yanıtlar:


176

Bunu yapmanın birden fazla yolu var:

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

Yansıma api'sini bile kullanabilirsiniz http://php.net/manual/en/class.reflection.php


Sanırım sözdizimini doğru yapmış olabilirim, yani kodumda tam olarak doğru çalışmadığı için başka bir sorun var. Hmm ...
VirtuosiMedia

Yöntemleriniz nesnelerde çağrılıyorsa ve PHPUnit ile test ediliyorsa, yorucu bir kelime, sizin call_user_func_arrayiçin olanıdır.
Tamam,

Sen benim arkadaşımsın, günümü kurtardın! Arıyordum call_user_func_array($this->$name, ...)ve neden işe yaramayacağını merak ettim!
Pubudu Dodangoda


10

PHP'de Aşırı Yüklemeyi kullanabilirsiniz: Aşırı Yükleme

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

PHP'de bir sınıf içinde çalışıyorsanız, PHP5'te aşırı yüklenmiş __call işlevini kullanmanızı tavsiye ederim. Referansı burada bulabilirsiniz .

Temel olarak __call, dinamik işlevler için __set ve __get'in OO PHP5'teki değişkenler için yaptığı şeyi yapar.


2

Bunca yıldan sonra hala geçerli! Kullanıcı tanımlı içerik ise $ methodName'i kırptığınızdan emin olun. Başında bir boşluk olduğunu fark edene kadar $ this -> $ methodName çalışamıyordum.


Kullanıcı tanımlı içerikse, adı kırpmaktan çok daha fazlasını yaptığınızdan emin olun! Mesela ... güvenlik kontrolü yap! ;)
Erk

İnternette bir yerde, kullanıcının girdiği utf8'i Windows güvenli karakterlere nasıl dönüştüreceğimi detaylandırdım. QuickBooks o atlatmak bana koştu - ve QB artık bir parçası olmasının nedeni nasıl komple satış ...
Chris K

Müşterinin, bazı yöntemleri dinamik olarak çağıran bir girdi belirlemesine gerçekten izin veriyor musunuz?
Sözüm

Açıkça doğrulandı ve sınıfın gerçekten böyle adlandırılmış bir yöntemi içerdiği kontrol edildi. Değeri kontrol etmenin birçok yolu vardır. Uzun bir anahtar ifadesini yener.
Snapey

1

Benim durumumda.

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

PHP SABUNU kullanma.


2
Emin değilim ama güvenlik sorunu konusunda dikkatli olun
tom10271

1

Bir yöntemi bir closure kullanarak tek bir değişkende depolayabilirsiniz:

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"

DÜZENLEME: Kodu düzenledim ve şimdi PHP 5.3 ile uyumlu. Burada başka bir örnek

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.