There are three ways serialization works in PHP:
# Basic serialization just dumps/restores all the properties of an object.
# Using `__sleep()` and `__wakeup()`, you can exclude some properties or do other code modifications.
# Using the `Serializable` interface lets you serialize to/from any arbitrary string. Often this string is created by calling `serialize()` recursively.
So what happens if you have an array with two objects, each of which contains the same third object?
``` lang=php
class Foo {
public $obj;
public function __construct( $obj ) {
$this->obj = $obj;
}
}
$obj = new stdclass;
$foo1 = new Foo( $obj );
$foo2 = new Foo( $obj );
$s = serialize( array( $foo1, $foo2 ) );
$data = unserialize( $s );
```
With either #1 or #2, it serializes that reference to $obj as a reference (code 'r') so when things are unserialized `$data[0]->obj === $data[1]->obj`.
``` name=without Serializable
a:2:{i:0;O:3:"Foo":1:{s:3:"obj";O:8:"stdClass":0:{}}i:1;O:3:"Foo":1:{s:3:"obj";r:3;}}
```
Originally, with method #3, it broke the reference so `$data[0]->obj` and `$data[1]->obj` would be clones of each other but would not be `===`.
``` name=Serializable without recursive state
a:2:{i:0;C:3:"Foo":35:{a:1:{s:3:"obj";O:8:"stdClass":0:{}}}i:1;C:3:"Foo":35:{a:1:{s:3:"obj";O:8:"stdClass":0:{}}}}
```
It seems that was reported as [[https://bugs.php.net/bug.php?id=36424|PHP bug 36424]]. The issue was eventually fixed in PHP 5.4.0 by making recursive calls to `serialize()` and `unserialize()` share state.
``` name=Serializable with recursive state
a:2:{i:0;C:3:"Foo":35:{a:1:{s:3:"obj";O:8:"stdClass":0:{}}}i:1;C:3:"Foo":20:{a:1:{s:3:"obj";r:4;}}}
```
Unfortunately it seems HHVM never picked up that fix ([[https://github.com/facebook/hhvm/issues/7253|HHVM bug 7253]]).
In {T209582} and {T210499}, this seems to have caused issues with the cache of the sidebar from `Skin::buildSidebar()`. When someone testing with PHP 7.2 triggers the cache, the serialized string uses a reference for Title objects inside of Message objects. When that serialized string is later fetched with HHVM, the lack of recursive state makes the unserialization fail.