PHP对象父/子递归

时间:2011-01-07 15:36:33

标签: php parent-child relationship

我有一个亲子OO关系。父对象具有许多子对象,并且每个子对象都通过引用知道它的父对象。

父母也可以是孩子(基本上是树)。

当我在根对象上执行 var_dump()时,它会多次显示 [“parent”] => RECURSION 生成的描述真的很长。

我想知道我是否做错了什么。如果是的话,我对“最佳实践”感兴趣。

感谢您的帮助!

3 个答案:

答案 0 :(得分:12)

你没有做错任何事;您有一个父项具有对其子项的引用,并且每个子项都有一个返回其父项的引用。当您var_dump()根对象时,它会遍历子项以打印它们,并且由于每个子项都有对父项的引用,因此它会向后移动。因为这通常会导致无限循环(parent - > child - > parent - > child - > ...),PHP会保留已访问过的对象列表,当遇到它时,它不会尝试再次转储它,而是打印“RECURSION”。

唯一要注意的是PHP使用引用计数进行垃圾收集,而像这样的循环结构本身并不能解决。因此,您的脚本将泄漏内存,这可能是也可能不是问题。要解决此问题,您需要手动清理:在父对象超出范围之前,您需要将所有父指针设置为null。

另请参阅:http://bugs.php.net/bug.php?id=33595

答案 1 :(得分:6)

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。你没有做错任何事。

Click here for another explanation

答案 2 :(得分:0)

你可以避免递归引用的唯一方法是构建一个“反向树”,这只是你想要在不知道兄弟姐妹的情况下从孩子到父母的搜索。像:

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,而不需要递归引用。

如果您需要从根节点转到子节点,那么除了您已经做过的事情之外没有其他解决方案,这是正确的。