带有循环引用的对象的in_array

Gor*_*onM 12 php arrays recursion object circular-reference

我正在构建一个对象数组.我需要这个数组只包含一个给定对象的实例,对同一个对象的多个引用应该抛出异常.我正在使用以下代码来实现此目的:

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);
}
Run Code Online (Sandbox Code Playgroud)

当我开始实现实现Node接口的对象时,这开始导致问题,因为它们可以包含循环引用(它们包含其子节点的集合,每个子节点都包含对其父节点的引用).尝试添加字段可能会导致生成以下错误:

PHP致命错误:嵌套级别太深 - 递归依赖?

我怀疑PHP正试图遍历整个对象数组,而不仅仅是比较对象引用,看它们是否保持相同的值,因此指向同一个对象.

我需要in_array做的只是将它存储的对象引用与字段的对象引用进行比较.这将阻止它尝试遍历整个对象树并遇到递归问题.

有办法做到这一点吗?

Gor*_*onM 21

事实证明,答案非常简单.看起来默认情况下,在测试针的草堆时,in_array会进行非严格比较(相当于==操作).这意味着它检查所有属性是否相等,这意味着它开始遍历对象图,如果您在该图中有循环引用,则可能会让您遇到麻烦.

然而,in_array函数有一个严格模式,据我所知,这相当于===操作.这似乎导致它检查引用以查看它们是否指向同一对象而不是比较所有属性.

只需将代码更改为:

if (!in_array ($field, $this -> fields, true))
Run Code Online (Sandbox Code Playgroud)

使该方法的行为符合我希望它在没有触发递归错误的情况下的行为.

我不得不说,我有点惊讶PHP默认情况下不执行此模式.另一方面,我想我真的不应该对PHP的弱打字再次引起我的问​​题感到惊讶.:)