2011-01-07 11 views
6

Posiadam relację rodzic-dziecko typu OO . Obiekty nadrzędne mają wiele obiektów podrzędnych, a każdy obiekt podrzędny wie o tym, że jest rodzicem przez odniesienie.Obiekt macierzysty/potomny obiektu rekurencyjnego PHP

Rodzic może być również dzieckiem (w zasadzie jest to drzewo).

Kiedy robię var_dump() na obiekcie głównym mówi [ „rodzic”] =>rekursji wiele razy i wygenerowany opis będzie naprawdę długa.

Zastanawiam się, czy zrobię coś nie tak. Jeśli tak, interesuje mnie "najlepsza praktyka".

Dzięki za pomoc!

+0

jakiś kod byłby niezły! –

+1

Wygląda na to, że masz swój wykres na wykresie (rodzic, który jest również dzieckiem jednego z jego potomków), ale nie widząc kodu ani przykładowych danych, trudno powiedzieć na pewno. – FrustratedWithFormsDesigner

+0

tak długo, jak jesteś pewien, że rekursja nie jest zbyt głęboka, jest w porządku. W przeciwnym razie mogą wystąpić problemy, np. kodowanie obiektu za pomocą json. – usoban

Odpowiedz

12

Nie robisz niczego złego; masz rodzica, który ma odniesienie do swoich dzieci, a każde dziecko ma odniesienie do swojego rodzica. Kiedy jesteś głównym obiektem, iteruje on nad dziećmi, aby je wydrukować, a ponieważ każde dziecko ma odniesienie do rodzica, to idzie z powrotem. Ponieważ normalnie spowoduje to nieskończoną pętlę (parent -> child -> parent -> child -> ...), PHP przechowuje listę obiektów, które już odwiedził, a kiedy napotka jeden, nie próbuje zrzucić ponownie, ale zamiast tego wyświetla "RECURSION".

Jedyna rzecz, na którą należy zwrócić uwagę, to fakt, że PHP używa licznika odwołań do zbierania śmieci, a konstrukcje kołowe takie jak te nie rozwiązują się same. W rezultacie twój skrypt spowoduje wyciek pamięci, co może, ale nie musi być problemem. Aby rozwiązać ten problem, należy ręcznie przeprowadzić czyszczenie: tuż przed wykryciem obiektu nadrzędnego należy ustawić wszystkie wskaźniki rodzicielskie na wartość null.

Zobacz także: http://bugs.php.net/bug.php?id=33595

+0

wyciek pamięci wydaje się być naprawiony od PHP 5.3: (patrz ostatnie 2 komentarze na: https://bugs.php.net/bug.php?id=33595) –

6

Funkcja var_dump podchodzi Twojego obiektu wykresu rekurencyjnie i wydrukować wszystkie dostępne dane swoich obiektów. Teraz spróbuj umieścić poniższy diagram w prostym języku angielskim.

 has    var_dump: 
Parent ----> Child   "The Parent object has a child object" 
^    |    "That Child object has a Parent Object" 
|______________| has    "That Parent object …" 

Jeśli PHP nie był wystarczająco inteligentny, aby wykryć tę rekursję, byłby uruchamiany w nieskończoność. Zamiast tego rozpoznaje, że wcześniej rzucił ten obiekt i zrzuca RECURSION. Nie robisz niczego złego.

Click here for another explanation

0

Jedynym sposobem można uniknąć odniesień rekurencyjnych jest przy budowie „odwróconego drzewa”, która jest przydatna tylko jest chcesz wyszukać od dziecka do rodzica, nie wiedząc, rodzeństwo. Jak:

class Foo { 
    protected $parent; 

    public function __construct(Foo $parent = null) { 
     $this->parent = $parent; 
    } 

    public function getParent() { 
     return $this->parent; 
    } 
} 

$a = new Foo; 
$b = new Foo($a); 
$c = new Foo($b); 

Więc od $c można śledzić aż do węzła głównego, będąc $a, bez odniesień rekurencyjnych.

Jeśli musisz przejść z węzła głównego do dzieci, to nie ma innego rozwiązania niż to, co już zrobiłeś, co jest poprawne.