采用以下PHP代码:
$a = new stdClass;
$b = $a;
var_dump(spl_object_hash($a) === spl_object_hash($b)); // true
list ($cachedA, $cachedB) = unserialize(serialize([$a, $b]));
var_dump(spl_object_hash($cachedA) === spl_object_hash($cachedB)); // true
$cachedA = unserialize(serialize($a));
$cachedB = unserialize(serialize($b));
var_dump(spl_object_hash($cachedA) === spl_object_hash($cachedB)); // false
似乎对象$ a和对象$ b,即使它们在序列化后是同一个对象,然后反序列化也有不同的哈希标识符。
有人可以解释这种预期的行为吗?
答案 0 :(得分:2)
如果您回显列表:
echo serialize([$a, $b]);
您正在获取数组,对象($ a)以及返回对象的引用($ b):
a:2:{i:0;O:8:"stdClass":0:{}i:1;r:2;}
这就是为什么它是真的。
我的猜测是两个不同的serialize / unserialize函数调用正在内存中创建两个不同的对象。
答案 1 :(得分:2)
这是完全可以预料的,事实上,serilizing / unserializing在很长一段时间内一直是一个廉价的克隆技巧。
spl_object_hash
实际上是PHP中对象的内存分配表中的一个地址。如果您认为散列不是其类型和属性值的结果,则更容易理解为什么具有相同属性的对象被分配了新散列。如果是,则哈希将不断变化。此外,如果你认为它是一个内存地址,那么你会意识到它首先需要在构造对象之前创建,因此,反序列化它会得到一个不同的。
从实施的角度来看,您可以想象为什么分配相同的地址是麻烦和危险的。第一个问题是内存地址或对象散列需要存储在序列化字符串中,内存地址在请求之间发生变化,因此跟踪它并非易事。此外,任何恶意用户都可以更改此哈希并指向地址空间中的任何位置,从而导致致命错误的分段错误。