spl_object_hash

(PHP 5 >= 5.2.0, PHP 7, PHP 8)

spl_object_hash 返回给定对象的哈希 ID

描述

spl_object_hash(object $object): string

此函数返回对象的唯一标识符。只要对象没有被销毁,此 ID 可以用作存储对象的哈希键,或者用于识别对象。一旦对象被销毁,其哈希可能会被其他对象重复使用。这种行为类似于 spl_object_id()

参数

object

任何对象。

返回值

一个字符串,对每个当前存在的对象都是唯一的,并且对每个对象始终相同。

示例

示例 #1 一个 spl_object_hash() 示例

<?php
$id
= spl_object_hash($object);
$storage[$id] = $object;
?>

注释

注意:

当对象被销毁时,其哈希可能会被其他对象重复使用。

注意:

对象哈希应该使用 ===!== 进行身份比较,因为返回的哈希可能是一个 数字字符串。例如:0000000000000e600000000000000000

参见

添加注释

用户贡献的注释 12 个注释

107
planetbeing
17 年前
请注意,该函数不会对对象的內容(属性)进行哈希,仅仅是对其内部句柄和句柄表指针进行哈希。这足以保证在内存中同时驻留的任何两个对象具有不同的哈希值。对于没有同时驻留内存中的对象,唯一性不保证,例如

var_dump(spl_object_hash(new stdClass()), spl_object_hash(new stdClass()));

单独运行此代码通常会生成相同的哈希值,因为 PHP 在创建第二个 stdClass 时,会在第一个 stdClass 被解除引用并销毁后重新使用其内部句柄。
70
mjs at beebo dot org
11 年前
请注意,对于两个不同的对象,spl_object_hash() 可以返回看起来非常相似的值,事实上,最显著的 *和* 最不显著的数字都可能相同!例如“000000003cc56d770000000007fa48c5”和“000000003cc56d0d0000000007fa48c5”。

因此(特别是如果您将此函数用于调试),您可能希望将哈希值传递给像 md5() 这样的加密哈希函数,以方便视觉比较,并使前几个或最后几个数字更可能唯一。

md5("000000003cc56d770000000007fa48c5") -> "619a799747d348fa1caf181a72b65d9f"

md5("000000003cc56d0d0000000007fa48c5") -> "ae964bc912281e7804fe5a88b4546cb2"
5
A simple developer
1 年前
在 PHP >= 8.1 中比较对象哈希时的注意事项

在 PHP 8.1(我认为)中,spl_object_hash() 的输出发生了变化(参见拉取请求 https://github.com/php/php-src/pull/7010)。
这导致了我们应用程序的奇怪行为,因为我们将对象哈希存储在数组中以检查我们是否已经处理了该对象。一个简单的 in_array() 检查返回 true,即使当前对象哈希实际上不在数组中。

实际问题:新的哈希值要简单得多,可以是类似“0000000000000e600000000000000000”或“0000000000000e490000000000000000”的东西,PHP 会将其解释为数字(指数)。
in_array() 默认情况下将进行非类型安全的比较,并将命名哈希解释为“0”。
29
aa dot vasilenko at gmail dot com
6 年前
请注意,从 PHP 7.2 开始,有一个新的函数可用 spl_object_id(),它返回 int 而不是字符串。它(应该是)更有效率。由于缺少文档,我建议您阅读 PR https://github.com/php/php-src/pull/2611
12
DimeCadmium
6 年前
对于那些认为此函数命名错误的人,我想引导您阅读 https://en.wikipedia.org/wiki/Hash_function。此外,对于那些认为它命名错误并提供与 Python 的比较的人,我想引导您阅读 https://docs.pythonlang.cn/2/library/functions.html#hash,它与此函数执行相同的操作。(来自 Python 的数据模型文档:“用户定义的类默认具有 __cmp__() 和 __hash__() 方法;... x.__hash__() 返回一个从 id(x) 导出的结果。” - id(x) 返回对象的内存地址。)

您所熟悉的加密哈希函数,如 MD5 或 SHA1,被称为哈希函数,因为它们具有类似的设计目标:低碰撞概率。
9
Hayleu Watson
7 年前
此函数名称中提到的“哈希”是指名为“哈希表”的存储结构,而不是任何形式的“消息摘要”。此函数返回的字符串不过是对象在 PHP 维持的所有现有对象的(哈希)表中的地址。
1
Numety
7 个月前
正如其他人所指出的,此函数现在返回 ID,并用零填充。
它不会生成加密哈希(这也不是名称所暗示的),也不会隐藏对象创建的顺序。

如果您希望为对象提供唯一标识符,同时隐藏它们的创建顺序,您可以通过将它们的 ID 与其他可预测的值一起哈希来实现。

<?php

function objectHash(object $object): string
{
return
hash('sha512', $object::class . spl_object_id($object));
}

?>

这是一个示例用法

<?php

class Person
{
function
__construct(public string $name) {}
}

$anna = new Person('Anna');
$bob = new Person('Bob');

var_export(objectHash($anna)); // '077d33c1 etc.
echo "\n";
var_export(objectHash($bob)); // 'ea3c1319 etc.

?>

请随意选择其他哈希,或者将其他值与其 ID 一起哈希,使其更适合您的环境。
2
Hayley Watson
1 年前
此函数比 spl_object_id 稍旧。它的输出更复杂,但实际上没有比新函数提供更多信息。它曾经复杂得多(但没有更多信息),但现在仅仅是对象的 ID 号以十六进制形式写出,并带有大量填充以保持旧格式。spl_object_id 只是将 ID 号作为普通整数给出。

您可能最好使用 spl_object_id,并考虑迁移如果您已经在使用 spl_object_hash;此函数有可能在将来被弃用,随后被删除。
-1
jasonlester at nope dot com
7 个月前
obj->handle 是一个无符号长整型,从 0 开始,每次创建对象时加 1,它不是像 mallaoc() 或类似函数创建的真正的指针。

/* {{{ 返回给定对象的整型对象句柄 */
PHP_FUNCTION(spl_object_id)
{
zend_object *obj;

ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_OBJ(obj)
ZEND_PARSE_PARAMETERS_END();

RETURN_LONG((zend_long)obj->handle);
}
/* }}} */

PHPAPI zend_string *php_spl_object_hash(zend_object *obj) /* {{{*/
{
return strpprintf(32, "%016zx0000000000000000", (intptr_t)obj->handle);
}
/* }}} */
-2
Hayley Watson
7 年前
此函数中提到的“哈希”是指“哈希表”这种存储结构的意义,而不是“消息摘要”的意义。
-5
Ulrich Eckhardt
7 年前
将此称为哈希非常具有误导性。

1. 此函数提供了一个对象标识符 (ID),它在整个生命周期内唯一标识对象。这类似于 C 中对象的地址或 Python 中的 id() 函数。我相信其他语言也有类似的结构。
2. 这不是哈希,与哈希无关。哈希接收数据并通过算法将数据缩减为某种标量值。唯一保证的是,两个相等的输入将提供相同的输出,但不能保证两个不同的输入将提供不同的输出(提示:哈希冲突)。spl_object_hash() 虽然保证了非相同对象的输出不同。
3. 正如某人已经提到的,这不会查看对象的内容。如果您考虑相等和同一性的区别,它只允许确定同一性。如果您序列化和反序列化一个对象,它将不再与其以前的自身相同,但它将是相等的,仅举一个例子。如果您想在响应缓存中使用密钥,在请求上使用此函数不仅毫无用处,因为相等的请求具有不同的 ID,而且可能是有害的,因为当请求对象被垃圾回收时,它的 ID 可以被重用。
-14
Hayley Watson
7 年前
此函数中提到的“哈希”是指“哈希表”这种存储结构的意义,而不是“消息摘要”的意义。
To Top