2011-12-10 25 views
12

Bir dizi nesne yapıyorum. Belirli bir nesnenin yalnızca bir örneğini içermek için bu diziye ihtiyacım var, aynı nesneye birden fazla başvuru olması bir istisna atmalıdır. Bunu başarmak için aşağıdaki kodu kullanıyorum:in_array Dairesel referanslara sahip nesneler üzerinde

public function addField ($name, iface\Node $field) 
{ 
    // Prevent the same field being added multiple times 
    if (!in_array ($field, $this -> fields)) 
    { 
     $this -> fields [$name] = $field; 
     $field -> setParent ($this); 
    } 
    else 
    { 
     throw new \InvalidArgumentException ('This field cannot be added to this group'); 
    } 
    return ($this); 
} 

Bu benim Düğüm arabirimini uygulamak nesneleri uygulamaya başladığı sorunlara yol açan başladı, bunlar dairesel referanslar içerebilir olarak (onların alt düğümleri bir koleksiyon tutun Her çocuğun ebeveynine referans göstererek). aşağıdaki hatayı neden olabilen bir alanı eklemek için çalışılıyor üretiliyor:

PHP Fatal error: Nesting level too deep - recursive dependency?

PHP tüm nesne dizide bilinçli çalışarak yerine sadece onlar aynı değeri tutmak olmadığını görmek için nesne referanslarını karşılaştıran ve şüpheleniyorsanız bu nedenle aynı nesneyi işaret eder.

Yapmak için in_array 'e ihtiyaç duyduğum şey, yalnızca başvurduğu nesne referanslarını alanın nesne referansı ile karşılaştırmaktır. Bu, tüm nesne ağacını çaprazlamaya ve özyineleme soruna girmeye çalışmasını engeller.

Bunu yapmanın bir yolu var mı?

+0

Amaçlarınız için daha uygun bir eşitlik denetimi yöntemi uygulamak için nesnenize '__equals' geçersiz kılmayı deneyin. –

cevap

16

Yanıtı son derece basittir. Varsayılan olarak, in_array'ın iğne için samanlığı test ederken katı olmayan karşılaştırmayı (bir == işlemine eşdeğer) yaptığı görülür. Bu, tüm özelliklerin eşit olduğunu, yani nesne grafiğini geçmeye başladığını ve bu grafikte döngüsel referanslarınız varsa sorun yaşayabileceğiniz anlamına gelir.

In_array işlevinin sıkı bir modu vardır, ancak söyleyebildiğim kadarıyla bir === işlemi eşdeğerdir. Bu, tüm özellikleri karşılaştırmak yerine aynı nesneyi gösterip göstermediklerini görmek için referansları kontrol etmesine neden olur.

Basitçe için kod değiştirme:

if (!in_array ($field, $this -> fields, true)) 

buna tekrarlama hatasını tetiklemeden davranmaya istediği gibi davranmasına yöntemini yapar.

PHP'nin bu modu varsayılan olarak yapmadığı konusunda biraz şaşırdığımı söylemeliyim. Diğer taraftan, PHP'nin zayıf yazımının tekrar bana bir soruna neden olduğu konusunda şaşmamalıyım. :)

1

Sadece SplObjectStorage veya spl_object_hash kullanırım.

Ve haklısınız, eğer php nesneleri karşılaştırırsa, yapıları birbirini takip eden şekilde (diziler) geçiyor.

+0

Sadece işaretçileri karşılaştırmanın bir yolu yok mu? – mifki

+1

@mifki Sıkı === karşılaştırması yapabilirsiniz. Nesnelerin puanlarını karşılaştıracaktır. – NikiC

+0

Yanıt için teşekkürler, ama sanırım bir çözüm buldum. – GordonM

İlgili konular