在PHP中比较对象相等性

11

具体细节

首先,在我的情况下,“相等”的定义是指当两个对象具有相同的结构和该结构的值时,它们是相等的。但是,它们可能不是同一个实例,或属性可能不处于相同的“顺序”(我的意思是,就像它们被分配/定义的那样)。在 Stack Overflow 上有类似的问题,例如这个问题,但它们没有涉及到我的情况。

出于测试代码的目的,我需要在 PHP 中比较实体 - 而这些实体可以是任何东西。特别地,它们可能是对象。然而,对象比较并不是“安全”的。想象一下你正在比较:

$result = $objectX == $objectY;

由于对象具有循环引用,可能导致致命错误。这里我准备了一个简单的例子(在此)。正如我们所看到的,PHP尝试跟随嵌套级别并陷入无限循环 - 因为对象本质上具有相同的内容,但具有循环引用。

重要细节是对象可能包含不可序列化的东西(例如闭包),这使得不能依赖于“序列化/反序列化”方法(即使忽略无序比较)。

目前的方法

我的代码类似于此处(复制粘贴太多了,但以防万一,这是一个要点)- 所以我在那里执行DFS,并捕获具有循环引用的情况。如您所见,它非常复杂 - 而且顺便说一句,它很慢。

当前方法的另一个问题是 - 当对象内部有数组时,它们将按照元素顺序进行比较,在某些情况下对我来说不太好(理想情况-当我能够切换排序方式比较时),但要本地解决这个问题,我可能需要以某种方式“排序”数组 - 我不知道如何做到这一点 - 因为这些数组元素的比较也不安全。

而且,循环数组引用也会导致失败:

$array = ['foo', $object, &$array];

问题

解决问题的其他(更好)途径是什么?序列化对象可能是一种选择,但由于属性集合的无序性,这对我来说行不通。


1
get_object_vars($objectX) == get_object_vars($objectY) - DaveRandom
@DaveRandom 不行,因为:1. 循环引用(主要点); 2. 无序属性比较(也是重要的一点)。 - Alma Do
1个回答

1

您是否了解Doctrine\Common\Util\Debug::export($class, $maxDepth)方法?

该方法“export”可以防止无限循环并返回可用于进行差异比较的数组。

超过一定深度后,不必再继续深入,通过$maxDepth参数,您可以指定比较的“精确度”。


查看了代码(http://www.doctrine-project.org/api/common/2.3/source-class-Doctrine.Common.Util.Debug.html#24-136)后发现该方法的设计依赖于`$maxDepth`,如果没有设置会导致失败。所谓“失败”,即不会执行任何有用的工作,只会打印出类名。 - Alma Do

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接