Richard
Richard

Reputation: 1172

In PHP 2 identical objects have 2 different hash keys once serialized

Take the following PHP code:

$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

It seems that object $a and object $b even though they are the same object once serialised and then deserialised have a different hash identifier.

Could someone explain is this expected behaviour?

Upvotes: 1

Views: 509

Answers (2)

This is completely expected, in fact serilizing/unserializing has been a cheap object cloning trick for quite a while.

spl_object_hash is a actually an address in the memory allocation table for objects in PHP. It is easier to understand why an object with the same properties gets assigned a new hash if you think that the hash is not the result of its type and properties values. If it were, then the hash would be changing constantly. Moreover, if you think as it as a memory address, then you realize that it first needs to be created before the object is constructed, thus, while unserializing it gets a different one.

From an implementation perspective, you can imagine why would assigning the same address is troublesome and dangerous. The first problem would be that the memory address, or object hash, would need to be stored in the serialized string, memory addresses change in between requests, so keeping track of that is not trivial. Additionally, any malicious user would then be able to alter this hash and point anywhere in the address space a cause segmentation faults of just fatal errors.

Upvotes: 2

pikuseru
pikuseru

Reputation: 71

If you echo out the list:

echo serialize([$a, $b]);

You're getting the array, the object ($a), and a reference back to the object ($b):

a:2:{i:0;O:8:"stdClass":0:{}i:1;r:2;}

So that's why it's true.

My guess is that the two different serialize/unserialize function calls are creating two different objects in memory.

spl_object_hash

PHP's serialize format

Upvotes: 2

Related Questions