سؤال

لقد قمت بتطبيق نمط مركب بسيط باستخدام 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;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top