5

上記の例のように、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);

また、SplObjectStorage の代わりに array() を使用して 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 に答える