I have implemented a simple Composite pattern using SplObjectStorage, like the example above:
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);
}
}
Whenever I try to serialize a Composite object, PHP 5.3.2 throws me a Segmentation Fault
.
This only happens when I add any number of nodes of any type to the object.
This is the offending code:
$node = new Node;
$composite = new Composite;
$composite->add($node);
echo serialize($composite);
Although this one works:
$node = new Node;
$composite = new Composite;
echo serialize($composite);
Also, if I implement the Composite pattern with array() instead of SplObjectStorage, all runs ok too.
What I'm making wrong?
By setting the Parent, you have a circular reference. PHP will try to serialize the composite, all of it's nodes and the nodes in turn will try to serialize the composite.. boom!
You can use the magic __sleep
and __wakeup()
methods to remove (or do whatever to the) the parent reference when serializing.
EDIT:
See if adding these to Composite
fixes the issue:
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With