不相关实体的Doctrine单一查询(用于仪表板)

时间:2016-01-11 10:11:17

标签: symfony join doctrine-orm outer-join

我有大约60个实体,都将(manyToOne或oneToOne)引用到称为“项目”的“超级实体”。

我正在开发一个仪表板,所以一旦选择了项目,我必须让所有“子”实体都参与该项目。

所以我有:

class Entity1{
...
/**
 * @ORM\OneToOne(targetEntity="Project")
 */
protected $project;
...
}

class Entity2{
...

/**
 * @ORM\ManyToOne(targetEntity="Project")
 */
protected $project;
...
}

我当然能做到:

    $entitiesToCheckStatusFor = ['Entity1', 'Entity2', ..., 'Entity60',  ];
    $entitiesStatus = [];
    foreach ($entitiesToCheckStatusFor as $entityToCheckStatusFor){
        $entitiesStatus[$entityToCheckStatusFor] = $em->getRepository('AppBundle:'.$entityToCheckStatusFor)->findByProject($project);
    }

但这意味着60个查询。它远非优雅。

我基本上需要在不相关的实体之间加入,以便我可以进行单个查询。

我尝试过类似的事情:

    $query = $em->createQuery('SELECT ai, pn, pb, pd p FROM AppBundle:Project p '
        . 'LEFT OUTER JOIN AppBundle:ProjectNotification pn WITH p.id = pn.project '
        . 'LEFT OUTER JOIN AppBundle:ProjectDetail pd WITH p.id = pd.project '
        . 'LEFT OUTER JOIN AppBundle:ProjectBenefit pb WITH p.id = pb.project '
        . 'LEFT OUTER JOIN AppBundle:ActionItem ai WITH p.id = ai.project '
        . 'WHERE p.id = :projectid'
    )->setParameter('projectid', $project->getId());
    $mixedStuff = $query->getResult();

但是当没有实体时它会返回很多空值:

array:20 [▼
  0 => Project {#8285 ▶}
  1 => null
  2 => ProjectDetail {#3028 ▶}
  3 => null
  4 => ActionItem {#2978 ▶}
  5 => null
  6 => null
  7 => ActionItem {#3191 ▶}
  8 => null
  9 => null
  10 => ActionItem {#3200 ▶}
  11 => null
  12 => null
  13 => ActionItem {#3205 ▶}
  14 => null
  15 => null
  16 => ActionItem {#3210 ▶}
  17 => null
  18 => null
  19 => ActionItem {#3214 ▶}
]

我可以忍受零,但我希望摆脱它们。除了在这种情况下,我希望得到2个空值(一个用于ProjectNotification,另一个用于ProjectBenefit,而我有很多。为什么?

还有其他建议吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

我没有看到使用LEFT OUTER JOIN的必要性。如果正确配置了关系,特别是在项目实体中,您可以创建一个简单的JOIN并获取非空值。

 $query = $em->createQuery('SELECT p, pn, pd,pb, pa '
        . 'FROM AppBundle:Project p '
        . 'JOIN p.notifications pn '
        . 'JOIN p.details pd '
        . 'JOIN p.benefits pb '
        . 'JOIN p.actions pa '
        . 'WHERE p.id = :id ')
        ->setParameter('id', $project->getId());