首页 > 解决方案 > 递归删除最低级别的孩子 Symfony/Doctrine

问题描述

我目前正在使用使用节点表中的节点的数据结构。它是自引用的,因为它有一个 id 和 parent_id 列。父子关系是一对多的。这意味着多个节点可以具有相同的 parent_id。这也可以在可变数量的级别中向下分支。

问题是我不能只删除父级,因为这在外键约束上失败了。这很好,因为我不希望孩子成为孤儿。然而,这确实意味着我必须递归地遍历孩子,直到我到达最低级别,删除那个孩子,然后重新开始工作。

到目前为止,我没有运气。这是我的“最佳”尝试,但是当我转储 toRemove 数组时,它总是为空。

/**
 * @var array
 */
private $toRemove;

/**
 * constructor.
 *
 * @param array $toRemove
 */
public function __construct(
    EntityManagerInterface $entityManager,
    array $toRemove = []
)
{
    $this->toRemove = $toRemove;
}

someMainFunc(blabla)
{
    foreach ($nodes as $node) {
        $this->removeChildrenFromLowestLevelUp($node)
    }
    dump($this->toRemove);die;
}

public function removeChildrenFromLowestLevelUp(Node $node)
{
    if (null === $node->getChildren()) {
        // Node has no children, add to toRemove array
        $this->toRemove[] = $node;
    }

    /** @var Node $child */
    foreach ($node->getChildren() as $child) {
        $this->removeChildrenFromLowestLevelUp($child);
    }
}

我知道互联网上有很多解决方案,但我不能让他们中的任何一个按照我想要的方式去做。

谢谢你的帮助!

标签: phpsymfonydoctrine

解决方案


你不想那样做。

首先,这意味着大量的查询和内存操作。其次,这是对轮子的再发明,因为这样的机制已经在数据库和 Doctrine 中实现了。

您可以在 Doctrine 级别使用cascade:remove此关系映射中的选项来执行此操作。查看文档以获取更多详细信息。

请记住,如文档中所述,所有相关对象都将从数据库加载到内存中,然后删除。这也意味着一些不必要的查询。

实现此目的的第二种方法是使用 SQL ON DELETE CASCADE,它做类似的事情,但在数据库级别。您可以使用映射中的选项在Doctrine中设置它。onDelete=CASCADE

根据您的描述,我会推荐第二种选择。


推荐阅读