使用DQL使用Therinsium2和Symfony2进行延迟加载

2022-08-30 12:58:17

我有一个带有父字段的树结构。目前,我正在尝试让所有父节点显示当前节点的路径。

基本上,我正在做一个 while 循环来处理所有节点。

$current = $node->getParent();
while($current) {
  // do something
  $current = $current->getParent();
}

使用默认方法有效。由于实体具有一些聚合字段,因此我使用自定义存储库方法,通过一个查询加载所有基本字段。findById

public function findNodeByIdWithMeta($id) {
    return $this->getEntityManager()
        ->createQuery('
            SELECT p, a, c, cc, ca, pp FROM
            TestingNestedObjectBundle:NestedObject p
            JOIN p.actions a
            LEFT JOIN p.children c
            LEFT JOIN c.children cc
            LEFT JOIN c.actions ca
            LEFT JOIN p.parent pp
            WHERE p.id = :id
        ')
        ->setParameter('id', $id)
        ->setHint(
            \Doctrine\ORM\Query::HINT_CUSTOM_OUTPUT_WALKER,
            'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
        )
        ->getOneOrNullResult();
}

使用该代码,加载父级将失败。我只得到直系父母(由)而不是上面的父母。例如: 返回。LEFT JOIN p.parent pp$node->getParent()->getParent()null

我的代码出了什么问题?我是否误解了延迟加载的事情?

非常感谢,Hacksteak


答案 1

看起来您正在使用邻接模型在关系数据库中存储树。这反过来意味着,您将需要为每个级别建立一个联接,以便通过一个查询获取所有祖先。

由于您已经在使用 Doctrine 扩展库,我建议您看一下 Tree 组件。


答案 2

我的答案涉及不使用DQL,而是创建一个可以访问您的DBAL连接的嵌套SetManager,以便您可以使用SQL。我从不觉得ORM在NestedSets查询逻辑方面做得很好。

使用 ,然后您可以编写一堆干净的方法,这非常简单,因为所有这些查询都有很好的文档记录。请参阅此链接。我的 NestedSetManager 中的一些方法是:NestedSetManager

setNode();
setRoot();
loadNestedSet();
moveNodeUp();
modeNodeDown();
getRootNode();
addNodeSibling();
getNodesByDepth();
getParents();
getNodePath();
childExists();
addChildToNode();
renameNode();
deleteNode();
// And many more 

你可以有一个球,并创建很多创建的嵌套集功能,如果你没有被ORM的一些复杂功能所束缚。

另外--Symfony2使这一切变得非常非常容易。创建 NestedSetManager 类文件,并在 Services.yml 中引用它,并在 Dbal 连接中传递。我的看起来像这样:

services:
    manager.nestedset:
        class: Acme\CoreBundle\Manager\NestedSetManager
        arguments: [ @database_connection ]

然后,您可以使用以下命令访问您的嵌套集:

$path = $this->get('manager.nestedset')->setNode(4)->getNodePath(); // in your controller

这个故事的寓意是,ORM / NestedSets让我发疯,这个解决方案效果非常好。如果您被迫使用DQL并且没有其他选择,则此答案可能不可接受。


推荐