Bir PHP nesne tanımsız bir yönteme cevap verebilir?

2 Cevap php

Raylar Ruby düzgün yönlerini bazı dayanır. Bunlardan biri tanımsız yöntemine cevap yeteneğidir.

Dog ve Owner. Sahibinden has_many :dogs ve Köpek belongs_to :owner arasındaki ilişkiyi düşünün.

Eğer giderseniz script/console, fido = Dog.find(1) ile bir köpek nesne olsun, ve o nesnenin bakarsanız, Owner. denilen bir yöntem ya da niteliğine görmezsiniz

Ne will gördüğünüz bir owner_id olduğunu. Eğer fido.owner sorarsan, nesne böyle bir şey (en azından bu benim için görünür nasıl) yapacak:

  1. Benim .owner nitelik için isteniyor. Ben onlardan biri yok!
  2. Ben bir atmadan NoMethodError, ben bu ile nasıl başa çıkılacağı konusunda bir kural var mı?
  3. Evet, biliyorum: Ben kontrol ve ben bir owner_id sahip olmadığını görmek gerekir.
  4. Yapmam! Tamam, o zaman ben bir katılmak ve bu sahibi nesneyi döndürmek yapacağız.

PHP'nin dokümantasyon - hım - Herkes burada bunun cevabını bilen varsa bazen biraz eksik, ben merak ediyorum:

Can I define similar behavior for objects in PHP?

Eğer değilse, esnek bir model için bir çözüm biliyor musunuz bu gibi katılır?

2 Cevap

Sen __call() method in PHP which is a catch all for calling an otherwise inaccessible yöntemini uygulayabilirsiniz.

class MyObj {
  public function __call($name, $args) {
    $list = $args ? '"' . implode('", "', $args) . '"' : '';
    echo "Call $name($list)\n";
  }
}

$m = new MyObj;
$m->method1(1, 2, 3);
$m->method2();

Bazı diller (örneğin, JavaScript) de first-class functions ne denir. Bu aslında size anında nesneler (ya da sınıfların) metotlarını eklemek veya kaldırmak için izin verir. (5,3 gibi) PHP sözdizimi sort of bunu destekler ama gerçekten kullanışlı değildir.

$obj = new stdClass;
$obj->foo = function() {
  echo "hello\n";
};

print_r($obj);

Çıktı:

stdClass Object
(
    [foo] => Closure Object
        (
        )

)

Ama deneyin:

$obj->foo();

ve olsun:

Fatal error:  Call to undefined method stdClass::foo() in C:\xampp\htdocs\test.php on line 8

Ancak;

$f = $obj->foo;
$f();

doğru çıkışlar hello.

Overloading to the rescue!

Biraz daha araştırma yaptıktan sonra, ne ben gerçekten istediğim olduğu anlaşılmaktadır PHP's overloading methods. Gordon verdi bağlantı ve sundukları özellikle indirilebilir Örneğin, at Kod çok aydınlatıcı oldu.

(Benim soru başlığı rağmen, ben gerçekten sonra tanımsız bir nesne cevap var ne oldu attributes.)

Yani, __get() ve __set() Eğer nesne özelliklerini almak ve ayarlamak için kullanılacak yöntemleri belirlemek, izin ve bu yöntemlerin içinde, böyle bir özellik varsa ne nesne söyleyebilir. Şimdilik sadece __get() bakalım.

Geri Dog örneğe dönecek olursak, bu gibi kullanabilirsiniz:

class Dog{
    // Private attributes, not accessible except through the __get method
    private $bark_volume = 'loud';
    private $owner_id = '5';
    public function __get($name){
        // If there's a property by that name, return it
        if (isset($this->$name)){
            return $this->$name;
        }
        // If not, let's see if there's an id with a related name;
        // if you ask for $this->owner, we'll check for $this->owner_id
        $join_id = $name . "_id";
        if(isset($this->$join_id)){
            // This is pretty useless, but the id could be used
            // to do a join query instead
            return $this->$join_id;
        }
    }
}

$Fido = new Dog;
echo $Fido->bark_volume; //outputs 'loud'
echo '<br/>';
echo $Fido->owner; //outputs '5'