Erreur sérialisation un arbre d'objets avec SplObjectStorage
-
01-10-2019 - |
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?
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;
}