使用SplObjectStorage序列化对象树时出错

时间:2010-08-27 11:26:45

标签: php serialization segmentation-fault composite spl

我使用SplObjectStorage实现了一个简单的Composite模式,如上例所示:

class Node
{
    private $parent = null;

    public function setParent(Composite $parent)
    {
        $this->parent = $parent;
    }
}

class Composite extends Node
{
    private $children;

    public function __construct()
    {
        $this->children = new SplObjectStorage;
    }

    public function add(Node $node)
    {
        $this->children->attach($node);
        $node->setParent($this);
    }
}

每当我尝试序列化Composite对象时,PHP 5.3.2都会抛出Segmentation Fault。 只有当我向对象添加任意类型的任意数量的节点时才会发生这种情况。

这是有问题的代码:

$node = new Node;
$composite = new Composite;
$composite->add($node);
echo serialize($composite);

虽然这个有效:

$node = new Node;
$composite = new Composite;
echo serialize($composite);

另外,如果我使用array()而不是SplObjectStorage实现Composite模式,那么所有运行也都可以。

我做错了什么?

1 个答案:

答案 0 :(得分:8)

通过设置Parent,您有一个循环引用。 PHP将尝试序列化复合,所有的节点和节点反过来将尝试序列化复合..繁荣!

您可以使用魔术__sleep and __wakeup()方法在序列化时删除(或执行任何操作)父引用。

修改

查看将这些内容添加到Composite是否解决了问题:

public function __sleep()
{
    $this->children = iterator_to_array($this->children);
    return array('parent', 'children');
}
public function __wakeup()
{
    $storage = new SplObjectStorage;
    array_map(array($storage, 'attach'), $this->children);
    $this->children = $storage;
}