使用PHP序列化维护对象关系

Ben*_*min 6 php oop serialization relationship

关于实现Serializable接口的对象,我遇到了一个非常棘手的问题.我们来举个例子:

class A {
    public $b;
}

class B {
    public $a;
}

$a = new A;
$b = new B;

$a->b = $b;
$b->a = $a;

echo serialize($a); // O:1:"A":1:{s:1:"b";O:1:"B":1:{s:1:"a";r:1;}}
echo serialize($b); // O:1:"B":1:{s:1:"a";O:1:"A":1:{s:1:"b";r:1;}}

$a = unserialize(serialize($a));
var_export($a === $a->b->a); // true
Run Code Online (Sandbox Code Playgroud)

我们可以在这个例子中看到,当使用内置的PHP序列化功能时(无论我们是否使用该__sleep()函数),A&之间的交叉引用B都被保留(r:1;).

但是,如果我们想强制使用Serializable接口,则会出现问题:

class A implements Serializable  {
    public $b;

    public function serialize() { return serialize($this->b); }
    public function unserialize($s) { $this->b = unserialize($s); }
}

class B implements Serializable {
    public $a;

    public function serialize() { return serialize($this->a); }
    public function unserialize($s) { $this->a = unserialize($s); }
}

$a = new A;
$b = new B;

$a->b = $b;
$b->a = $a;

echo serialize($a); // infinite loop crashes PHP
Run Code Online (Sandbox Code Playgroud)

因为每个对象序列化都是独立管理的,所以没有全局方法来查看对象是否已经被序列化,以创建对它的引用.serialize()然后在无限循环中调用这些函数.

这个问题有一个很好的解决方法吗?用于serialize()功能的模式?

Ben*_*min 3

Doctrine 项目在其关于序列化实体的文档中将这个问题命名为循环对象引用:

Serialized 不能很好地处理任何潜在的循环对象引用(至少我们还没有找到方法,如果您找到了,请联系我们)。

所以,据我所知,目前这个问题还没有通用的解决方案。