2011-12-10 38 views
12

Tôi đang xây dựng một mảng các đối tượng. Tôi cần mảng này để chỉ chứa một lần của một đối tượng nhất định, có nhiều tham chiếu đến cùng một đối tượng nên ném một ngoại lệ. Tôi đang sử dụng đoạn mã sau để đạt được điều này:in_array trên các đối tượng có tham chiếu vòng tròn

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); 
} 

này bắt đầu dẫn đến các vấn đề khi tôi bắt đầu thực hiện các đối tượng mà thực hiện giao diện Node, vì chúng có thể bao gồm tài liệu tham khảo tròn (họ giữ một bộ sưu tập của các nút con của họ , với mỗi đứa trẻ giữ một tham chiếu đến cha mẹ của nó). Cố gắng để thêm một lĩnh vực có thể dẫn đến các lỗi sau được tạo ra:

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

Tôi nghi ngờ rằng PHP đang cố gắng đi qua toàn bộ mảng đối tượng, thay vì chỉ so sánh các tham chiếu đối tượng để xem nếu họ giữ giá trị như nhau và do đó chỉ vào cùng một đối tượng.

Điều tôi cần in_array để làm là chỉ so sánh các tham chiếu đối tượng mà nó lưu trữ với tham chiếu đối tượng của trường. Điều này sẽ ngăn chặn nó cố gắng đi qua toàn bộ cây đối tượng và chạy vào vấn đề đệ quy.

Có cách nào để thực hiện việc này không?

+0

Hãy thử ghi đè '__equals' trên đối tượng của bạn để triển khai phương pháp kiểm tra bình đẳng phù hợp hơn cho mục đích của bạn. –

Trả lời

16

Hóa ra câu trả lời cực kỳ đơn giản. Nó sẽ xuất hiện rằng theo mặc định in_array không so sánh nghiêm ngặt (tương đương với một hoạt động ==) khi kiểm tra haystack cho kim. Điều này có nghĩa là nó kiểm tra rằng tất cả các thuộc tính đều bằng nhau, có nghĩa là nó bắt đầu duyệt qua biểu đồ đối tượng và điều đó có thể khiến bạn gặp rắc rối nếu bạn có tham chiếu vòng tròn trong biểu đồ đó.

Chức năng in_array có chế độ nghiêm ngặt, tuy nhiên, theo như tôi có thể biết thì tương đương với thao tác ===. Điều này dường như làm cho nó để kiểm tra các tài liệu tham khảo để xem họ chỉ vào cùng một đối tượng thay vì so sánh tất cả các thuộc tính.

Đơn giản chỉ cần thay đổi mã để:

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

làm cho các phương pháp hành xử như tôi muốn nó cư xử mà không có nó kích hoạt các lỗi đệ quy.

Tôi phải nói rằng tôi hơi ngạc nhiên khi PHP không thực hiện chế độ này theo mặc định. Mặt khác, tôi đoán tôi thực sự không nên ngạc nhiên khi việc đánh máy yếu của PHP đã khiến tôi gặp vấn đề một lần nữa. :)

1

Tôi chỉ sử dụng SplObjectStorage hoặc spl_object_hash.

Và bạn nói đúng, khi php so sánh mọi thứ, nó truyền tải cấu trúc đệ quy (mảng quá).

+0

Không có cách nào để so sánh chỉ con trỏ? – mifki

+1

@mifki Bạn có thể thực hiện loại so sánh === nghiêm ngặt. Nó sẽ so sánh điểm cho các đối tượng. – NikiC

+0

Cảm ơn bạn đã phản hồi, nhưng tôi nghĩ tôi đã tìm được giải pháp. – GordonM

Các vấn đề liên quan