PHP - 以某种方式散列对象,具有相同字段值的 distint 对象具有相同的散列

Hip*_*ith 5 php hash performance

我正在寻找一种为 PHP 对象生成某种哈希的方法(通用解决方案,如果可能,可以使用所有分类的、内置的和自定义的)。

SplObjectStorage::getHash 不是我要找的,因为它会为给定类的每个实例生成不同的哈希。为了描绘这个问题,让我们考虑一个简单的类:

class A() {
public $field; //public only for simplicity
}
Run Code Online (Sandbox Code Playgroud)

以及该类的 2 个实例:

$a = new A(); $a->field = 'b';
$b = new A(); $b->field = 'b';
Run Code Online (Sandbox Code Playgroud)

我尝试过的每个内置函数都会为这些对象返回不同的哈希值,而我想要一些function f($x)带有 property 的f($a) == f($b) => $a == $b

我知道我可以编写一个递归遍历所有对象属性的函数,直到找到一个可以转换为字符串的属性,以奇特的方式连接这些字符串和散列,但这种解决方案的性能会很糟糕。

有没有一种有效的方法来做到这一点?

eva*_*cha 5

假设我理解正确,您可以序列化对象,然后对序列化对象进行 md5 处理。由于如果所有属性都相同,序列化会创建相同的字符串,因此每次都应该获得相同的哈希值。除非您的对象具有某种时间戳属性。例子:

class A {
    public $field;
}
$a = new A;
$b = new A;
$a->field = 'test';
$b->field = 'test';
echo md5(serialize($a)) . "\n";
echo md5(serialize($b)) . "\n";
Run Code Online (Sandbox Code Playgroud)

输出:

0a0a68371e44a55cfdeabb04e61b70f7
0a0a68371e44a55cfdeabb04e61b70f7
Run Code Online (Sandbox Code Playgroud)

你的结果会有所不同,因为 php 内存中的对象存储有每个实例化的编号 id:

object(A)#1 (1) {...
object(A)#2 (1) {...
Run Code Online (Sandbox Code Playgroud)

  • 当然,*内部*这正是OP所建议的:“递归遍历所有对象的属性......转换为字符串,连接......以奇特的方式”。但这种方式比尝试在用户空间中实现所有这些更有效且更不容易出错。:) (2认同)
  • 需要明确的是,我认为序列化可能是正确的解决方案,并对你的答案投了赞成票。最终,任何需要比较两个深层结构的值的事情都必须递归地检查这些结构 - 无论是“serialize”、“var_dump”还是手动堆栈和循环。即使使用原始内存访问,您也需要递归地跟踪指向其他内存区域的指针。类似地,任何需要散列数据结构的东西都必须首先将其展平为标准字节表示形式,因此也无法避免字符串转换。 (2认同)