PHP объект родительская / дочерняя рекурсия - PullRequest
6 голосов
/ 07 января 2011

У меня родительско-дочерние ОО отношения . У родительских объектов есть много дочерних объектов, и каждый дочерний объект знает о своем родителе по ссылке.

Родитель тоже может быть ребенком ( в основном это дерево ).

Когда я делаю var_dump () для корневого объекта, он говорит ["parent"] => RECURSION много раз, и сгенерированное описание будет очень долго.

Мне интересно, если я что-то не так делаю. Если да, меня интересует «лучшая практика».

Спасибо за помощь!

Ответы [ 3 ]

12 голосов
/ 07 января 2011

Вы не делаете ничего плохого;у вас есть родитель, у которого есть ссылка на своих потомков, и у каждого ребенка есть ссылка на своего родителя.Когда вы var_dump() корневой объект, он перебирает дочерние элементы, чтобы напечатать их, и, поскольку каждый дочерний элемент имеет ссылку на родительский объект, он возвращается обратно.Поскольку это обычно вызывает бесконечный цикл (parent -> child -> parent -> child -> ...), PHP хранит список объектов, которые он уже посетил, и когда он встречает один, он не пытается сброситьон снова, но вместо этого печатает «RECURSION».

Единственное, на что следует обратить внимание, это то, что PHP использует подсчет ссылок для своей сборки мусора, и подобные циклические конструкции не разрешаются сами по себе.В результате у вашего скрипта будет утечка памяти, что может быть или не быть проблемой.Чтобы решить эту проблему, вам нужно выполнить очистку вручную: непосредственно перед тем, как родительский объект выйдет из области видимости, вам нужно установить все родительские указатели на null.

См. Также: http://bugs.php.net/bug.php?id=33595

6 голосов
/ 07 января 2011

Функция var_dump рекурсивно обходит ваш граф объектов и печатает все доступные данные ваших объектов. Теперь попробуйте поместить приведенную ниже диаграмму на простой английский.

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

Если бы PHP не был достаточно умен, чтобы обнаружить эту рекурсию, он работал бы бесконечно. Таким образом, вместо этого он распознает, что ранее он сбрасывал этот объект, и выводит RECURSION. Вы не делаете ничего плохого.

Нажмите здесь для другого объяснения

0 голосов
/ 07 января 2011

Единственный способ избежать рекурсивных ссылок - это создать «перевернутое дерево», которое полезно только в том случае, если вы хотите осуществлять поиск от дочернего элемента к родительскому, не зная родных элементов.Например:

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

Итак, с $c вы можете отслеживать до корневого узла, будучи $a, без рекурсивных ссылок.

Если вам нужно перейти с корневого узладля детей, тогда нет другого решения, чем то, что вы уже сделали, и это правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...