在PHP中克隆父子树,从子节点开始,避免无休止的递归

发布时间:2022-04-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了在PHP中克隆父子树,从子节点开始,避免无休止的递归脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
我在 PHP中有一个面向对象的父子树,我想要克隆.
困难的部分是对树的访问并不总是通过根,但有时通过根的子进程,如下所示:

[Root]
  -- [Element1] START CLONE
       -- [Element3]
       -- [Element4]
  -- [Element2]
       -- [Element5]

所以我想做的是克隆整个树,通过调用$new = clone $element1;

__clone()方法声明还必须克隆每个子节点,并且,如果出现图示的情况*,则还必须克隆父节点.

* Root在Element1中显式设置为父级,因此系统可以识别这种情况并对其执行某些操作.

问题是,从Element1开始克隆操作时,还必须克隆Root. Root的克隆过程规定必须克隆所有子元素,因此再次调用Element1的克隆操作,然后重复相同的克隆过程,产生无限循环.

此外,Root不会包含Element1的第一个克隆,但它会生成自己的克隆以作为子元素添加.然后,Element1将Root作为其父级,但Root将不具有与子级相同的Element1.

我希望我能以清晰的方式提出问题,有人可以帮我找到解决方案.

编辑:

最终解决方

/**
 * The $replace and $wITh arguments allow a custom @R_771_1419@ PRocedure. Instead of
 * being cloned,the original child $replace will be replaced by $with.
 */
public function duplicate($replace = null,$with = null) {
    // Basic @R_771_1419@
    $clone = clone $this;
    // If parent is set
    if(isset($this->parent)) {
        // Clone parent,replace this element by its clone
        $parentClone = $this->parent->duplicate($this,$clone);
        $clone->parent = $parentClone;
    }

    // Remove all children in the clone
    $clone->clear();

    // Add cloned children From original to clone
    foreach($this->getChildren() as $child) {
        if($child === $replace)
            // If @R_771_1419@ was initiated from this child,replace with given clone
            $childClone = $with;
        else
            // Else duplicate child normally
            $childClone = $child->duplicate();

        // Add cloned child to this clone
        $clone->add($childClone);
    }

    return $clone;
}

解决方法

首先,简化您的示例:

[Root]
  -- [Element1] START CLONE
       -- [Element3]

然后你做的不同,我认为你有三个操作

>公共克隆方法.
>自我克隆操作,返回带子节点的克隆,但不返回父节点.
>单克隆操作,返回没有子节点的克隆.

类之外的代码使用公共克隆方法.但是__clone()方法不能使用该方法,否则会遇到您所描述的循环循环问题.所以__clone()实现必须使用其他方法.

将cloneSelf和cloneSingle方法添加到您的类中,使它们受到保护,因此继承的类可以调用它们,但它们不公开.

然后在__clone()实现中使用它们:

public function clone()
{
    // clone the parent
    $parent = $this->getParent();
    $parentClone = $parent->cloneSingle();

    // clone all children of parent which includes $this
    $selfclone = NULL;
    foreach($parent->getChildren() as $child)
    {
        $childClone = $child->cloneSelf();
        if (!$selfClone && $child === $this)
            $selfClone = $childClone;
        $parentClone->addChild($childClone);

    }

    assert('$selfClone');

    return $selfClone;
}

public function __clone()
{
    $message = 'Clone operator is not Allowed,use clone() method instead.';
    throw new BadMethodCallException($message);
}

这些方法还可以帮助您在没有父级的情况下进行克隆.

脚本宝典总结

以上是脚本宝典为你收集整理的在PHP中克隆父子树,从子节点开始,避免无休止的递归全部内容,希望文章能够帮你解决在PHP中克隆父子树,从子节点开始,避免无休止的递归所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。