Anında bir php nesnesine yeni bir yöntem eklemek nasıl?

5 Cevap php

Nasıl "fly" bir nesneye yeni bir yöntem eklerim?

$me= new stdClass;
$me->doSomething=function ()
 {
    echo 'I\'ve done something';
 };
$me->doSomething();

//Fatal error: Call to undefined method stdClass::doSomething()

5 Cevap

Update: Burada gösterilen yaklaşım, büyük bir eksiklik var: Yeni işlev sınıfının tam üyesi değildir; Bu şekilde çağrıldığında $this yöntem mevcut değildir. Bu nesne örneği veri veya fonksiyonları ile çalışmak istiyorsanız, bir parametre olarak işleve nesneyi geçmek zorunda anlamına gelir! Ayrıca, private veya bu fonksiyonların gelen sınıf protected üyelere erişmek mümkün olmayacaktır.

Güzel bir soru ve zekice bir fikir yeni bir anonim işlevleri kullanarak!

İlginçtir, bu işleri: Değiştir

$me->doSomething();    // Doesn't work

call_user_func tarafından on the function itself:

call_user_func($me->doSomething);    // Works!

ne işe yaramazsa "doğru" yolu:

call_user_func(array($me, "doSomething"));   // Doesn't work

bu şekilde çağrılırsa, PHP sınıf tanımında ilan edilmesi için yöntem gerektirir.

Bu bir private / public / protected görünürlük sorunu var mı?

Update: Hayır. Hatta sınıf içinde işlevini normal yoldan aramak için imkansız, bu yüzden bu bir görünürlük sorun değildir. Için gerçek işlevini iletme call_user_func() Ben bu işi yapmak için görünebilir tek yoludur.

Bir similar post on stackoverflow bu bazı tasarım desenleri uygulanması yoluyla sadece ulaşılabilir olduğunu ortaya temizler var.

Diğer tek yolu classkit, deneysel php uzantısının kullanılmasıdır. (Ayrıca sonrası)

Yes it is possible to add a method to a PHP class after it is defined. You want to use classkit, which is an "experimental" extension. It appears that this extension isn't enabled by default however, so it depends on if you can compile a custom PHP binary or load PHP DLLs if on windows (for instance Dreamhost does allow custom PHP binaries, and they're pretty easy to setup).

Burada anonim fonksiyonu ayarlamak için izin basit bir sınıf. Bu https://gist.github.com/nickunderscoremok/5857846, optimize edilmiş bir sınıf bulunuyor

<?php
class stdObject {
    public function __construct(array $arguments = array()) {
        if (!empty($arguments)) {
            foreach ($arguments as $property => $argument) {
                if ($argument instanceOf Closure) {
                    $this->{$property} = $argument;
                } else {
                    $this->{$property} = $argument;
                }
            }
        }
    }

    public function __call($method, $arguments) {
        if (isset($this->{$method}) && is_callable($this->{$method})) {
            return call_user_func_array($this->{$method}, $arguments);
        } else {
            throw new Exception("Fatal error: Call to undefined method stdObject::{$method}()");
        }
    }
}

$person = new stdObject(array(
    "name" => "nick",
    "age" => 23,
    "friends" => array("frank", "sally", "aaron"),
    "sayHi" => function() {
        return "Hello there";
    }
));

$person->sayHi2 = function() {
    return "Hello there 2";
};

$person->test = function() {
    return "test";
};

var_dump($person->name, $person->test(), $person->sayHi2());
?>

Eval ile bunu nasıl görmek için, github geçerli benim PHP mikro çerçevede, Halcyon, bir göz atabilirsiniz. HalcyonClassMunger sınıf konsantre - Bu herhangi bir sorun olmadan onu anlamaya muktedir gerektiği kadar küçük.