我可以通过检查id对null来优雅地与Doctrine联系吗?

时间:2018-03-26 17:46:29

标签: php symfony doctrine symfony-2.8

我已经实现了以下功能,这与我真正想要的非常接近:

public function loadUserGroupsOfNewsletter($ids, $newsletterID)
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    return $qb->select('ug, gon')
              ->from('MyNameSpace:UserGroup', 'ug')
              ->leftJoin('ug.groupsOfNewsletter', 'gon')
              ->leftJoin('gon.newsletterItem', 'n')
              ->where($qb->expr()->in('ug.id', $ids))
              ->where('n.id = :id')
              ->setParameter('id', $newsletterID)
              ->getQuery()->getResult();
}

我想为每个用户组至少获得一条记录。如果没有与时事通讯的ID匹配的简报,那么我希望gonnull给定的结果项,但如果至少有一个与该ID匹配的时事通讯,那么我想在结果项中包含正确的用户组和gon记录。

所以,

案例1.给定的用户组没有匹配的简报:

结果项应包含正确的ugnull gon

案例2.给定的用户组至少有一个匹配的简报:

通讯项目数量与此类匹配项一样多,此用户组的所有结果项都包含有效的uggon

我试图检查n.id是否为null,结果符合我的期望,所以我假设以下查询实现了我的意图,因为我的实验产生了良好的结果。我在这个假设中是对的吗?

public function loadUserGroupsOfNewsletter($ids, $newsletterID)
{
    $qb = $this->getEntityManager()->createQueryBuilder();
    return $qb->select('ug, gon')
              ->from('MyNameSpace:UserGroup', 'ug')
              ->leftJoin('ug.groupsOfNewsletter', 'gon')
              ->leftJoin('gon.newsletterItem', 'n')
              ->where($qb->expr()->in('ug.id', $ids))
              ->where('(n.id is null) or (n.id = :id)')
              ->setParameter('id', $newsletterID)
              ->getQuery()->getResult();
}

1 个答案:

答案 0 :(得分:1)

从它的外观来看,应该没问题,但是我不确定你想要通过返回订阅这个特定时事通讯的用户和未订阅的用户来实现什么任何

您可以尝试将这些谓词移至IN声明(WITH中的Doctrine):

->leftJoin('ug.groupsOfNewsletter', 'gon')
->leftJoin('gon.newsletterItem', 'n', 'WITH', 'n.id = :id')

这有意义吗?也许我误解了你的意图。

另一件引起我注意的事情是where的双重使用。根据{{​​1}}的来源,where看起来像这样:

Doctrine

add有以下签名:

public function where($predicates)
{
    if (! (func_num_args() === 1 && $predicates instanceof Expr\Composite)) 
    {
        $predicates = new Expr\Andx(func_get_args());
    }

    return $this->add('where', $predicates);
}

换句话说,您的后续public function add($dqlPartName, $dqlPart, $append = false) 将不会被追加,而是会覆盖之前的where

你应该使用andWhere来做你想做的事。

希望这有点帮助...