خطأ تسلسل شجرة كائن مع 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);
أيضًا ، إذا قمت بتطبيق النمط المركب باستخدام Array () بدلاً من SplobjectStorage ، فكلها تعمل بشكل جيد أيضًا.
ما الذي أخطأ؟
المحلول
من خلال تعيين الوالد ، لديك مرجع دائري. ستحاول 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;
}
لا تنتمي إلى StackOverflow