Question

J'ai mis en place un modèle simple composite en utilisant SplObjectStorage, comme dans l'exemple ci-dessus:

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);
    }
}

Chaque fois que je tente de sérialiser un objet composite, PHP 5.3.2 me jette un Segmentation Fault. Cela ne se produit quand j'ajoute un certain nombre de noeuds de tout type à l'objet.

Ceci est le code incriminé:

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

Bien que celui-ci fonctionne:

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

En outre, si je mets en œuvre le modèle composite avec array () au lieu de SplObjectStorage, tout fonctionne bien aussi.

Qu'est-ce que je fais mal?

Était-ce utile?

La solution

En définissant le parent, vous avez une référence circulaire. PHP va essayer de sérialiser le composite, tous les nœuds de noeuds et il à son tour essayer de sérialisation composite .. boom!

Vous pouvez utiliser la magie __sleep et __wakeup() méthodes de retirer (ou faire tout à) la référence parent lors de la sérialisation.

EDIT:

Voir si les ajouter à des corrections de Composite la question:

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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top