2024年PHP开发者大会日本站

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

参见

添加注释

用户贡献的注释 11 个注释

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

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

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

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

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

md5("000000003cc56d0d0000000007fa48c5") -> "ae964bc912281e7804fe5a88b4546cb2"
A simple developer
一年以前
在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”。
aa dot vasilenko at gmail dot com
6年前
请注意,从PHP 7.2开始,可以使用新的函数spl_object_id(),它返回int而不是string。它(应该)更高效。由于缺乏文档,我建议您阅读PR https://github.com/php/php-src/pull/2611
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,之所以被称为哈希函数,是因为它们具有相似的设计目标:碰撞概率低。
Hayleu Watson
7年前
此函数名称中提到的“哈希”是指称为“哈希表”的存储结构,而不是任何类型的“消息摘要”。此函数返回的字符串只不过是PHP维护的所有现有对象的(哈希)表中的对象的地址。
Numety
11个月前
正如其他人所指出的,此函数现在返回用零填充的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 等。
echo "\n";
var_export(objectHash($bob)); // 'ea3c1319 等。

?>

您可以自由选择其他哈希算法,或者将其他值与它们的 ID 一起进行哈希,以更好地适应您的环境。
Hayley Watson
一年以前
此函数略早于 `spl_object_id`。它的输出更复杂,但实际上并没有提供比新函数更多的信息。它过去更加复杂(但信息量并没有更多),现在只是对象的 ID 号以十六进制形式写出,并添加了许多填充以保持旧格式。`spl_object_id` 只是将 ID 号作为普通整数给出。

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

/* {{{ 返回给定对象的整数对象句柄 */
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);
}
/* }}} */
Hayley Watson
7年前
此函数中提到的“哈希”是指被称为“哈希表”的存储结构,而不是“消息摘要”的意思。
Ulrich Eckhardt
7年前
将此称为哈希非常具有误导性

1. 此函数提供对象标识符 (ID),它在对象的整个生命周期内唯一标识该对象。这类似于 C 中对象的地址或 Python 中的 `id()` 函数。我相信其他语言也有类似的结构。
2. 这不是哈希,并且与哈希无关。哈希采用数据并通过算法将该数据简化为某种标量值。唯一的保证是两个相等的输入产生相同的输出,但不能保证两个不同的输入产生不同的输出(提示:哈希冲突)。`spl_object_hash()` 虽然保证了非相同对象的输出不同。
3. 正如其他人已经提到的那样,这不会查看对象的内容。如果您考虑相等和同一性之间的区别,它只允许确定同一性。如果您序列化和反序列化一个对象,它将与其之前的自身不相同,但它将是相等的,这只是一个例子。如果您想要一个用于响应缓存的键,那么在此函数上对请求进行操作不仅没有用,因为相等的请求具有不同的 ID,而且可能还会造成危害,因为当请求对象被垃圾回收时,其 ID 可以被重用。
To Top