使用DQL延迟加载Doctrine2和Symfony2

时间:2011-11-05 16:36:50

标签: php symfony doctrine-orm

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

基本上我正在做一个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

2 个答案:

答案 0 :(得分:7)

看起来您正在使用adjacency model在关系数据库中存储树。这反过来意味着,您将需要每个级别的联接,以通过单个查询获得所有祖先。

由于您已经在使用Doctrine Extension Library,我建议您查看Tree组件。

答案 1 :(得分:2)

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

使用NestedSetManager,您可以编写一堆干净的方法,它非常简单,因为所有这些查询都有详细记录。见this link。我的NestedSetManager中的一些方法是:

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

如果您没有被ORM的某些复杂功能所束缚,您可以拥有一个球并创建大量创建NestedSet功能。

另外 - 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并且没有其他选择,那么这个答案可能是不可接受的。