5

我已经使用 SplObjectStorage 实现了一个简单的复合模式,如上面的示例:

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 模式,所有运行也正常。

我做错了什么?

4

1 回答 1

8

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

您可以在序列化时使用魔法__sleep__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;
}
于 2010-08-27T11:44:44.930 回答