Ошибка сериализации дерева объекта с SplobjectStorage
-
01-10-2019 - |
Вопрос
Я внедрил простой композитный шаблон с помощью 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);
}
}
Всякий раз, когда я пытаюсь сериализовать композитный объект, 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, все работает хорошо.
Что я делаю не так?
Решение
Установив родитель, у вас есть круговая ссылка. PHP попытается сериализовать композит, все его узлы и узлы, в свою очередь, попытаются сериализовать композит .. Boom!
Вы можете использовать магию __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;
}