原则 2:将查询生成器用于多对多关系



为了在系统中搜索人员,我在存储库中编写了一个函数。此函数接收包含字段名称和条件的数组,并使用查询生成器来表述有效的 DQL 语句。

一切正常,直到我想制定如下搜索规则的那一刻:

"找到属于某个领域的所有人。"

。其中,"个人"和"域"实体具有多对多关系。

根据Symfony2的说法,这种关系的定义是正确的,实际上一切都在Twig模板和控制器中工作。

该函数如下所示:-

private function query($extra_conditions = null)
{
    $qb = $this->_em->createQueryBuilder();
    $query =
    $qb->select('p')
    ->from('AppMainBundle:Person', 'p')
    ->leftjoin('AppMainBundle:Domain', 'd')
    ->where("p.firstname IS NOT NULL")
    ->andWhere("p.lastname IS NOT NULL")
    ->andWhere("p.function IS NOT NULL");
    if ($extra_conditions!=null)
    {
        foreach ($extra_conditions as $condition)
        {
            #filter on firstname
                if (key($condition)=='firstname')
                    $query = $query->andWhere('p.firstname LIKE ?1')
                    ->setParameter(1, $condition['firstname']);
            #filter on lastname
                if (key($condition)=='lastname')
                    $query = $query->andWhere('p.lastname LIKE ?1')
                    ->setParameter(1, $condition['lastname']);
            #filter on gender
                if (key($condition)=='gender')
                    $query = $query->andWhere('p.gender = '.$condition['gender']);
            #filter on domain(s)
                if (key($condition)=='domains')
                    $query = $query->andWhere('d.id IN ('.$condition['domains'].')');
            #filter on town
                if (key($condition)=='town')
                    $query = $query->andWhere('p.town LIKE ?1')
                    ->setParameter(1, $condition['town']);
        }
    }
    $query = $query->orderBy("p.lastname", "ASC");
    $query = $qb->getQuery();
    return $query->getResult();
}

没有错误,但无论给出什么域作为搜索条件;找到并返回来自所有域的人员。

域以数组的形式提供,如 (2, 4)。

我可以更改哪些内容才能找到属于某些域的人员?

经过一些反复试验,我找到了两个可能的答案:

1)显然,在查询构建器中,您可以引用位于连接表中的字段,并且实际上不是实体的一部分。因此,一种解决方案是:

#filter on domain(s)
    if (key($condition)=='domains')
        $query = $query->andWhere('p.domain_id IN ('.$condition['domains'].')');

。其中domain_id位于由 Symfony2 创建的连接表"person_domain"中。

2) 现在不再需要内部联接。也可以使用内部连接,但是它以错误的方式编写,无论如何都不会起作用。它应该写成:

->leftjoin('p:domain', 'd', 'ON p.id = d.id')

希望其他人可以从上述内容中受益。

相关内容

  • 没有找到相关文章

最新更新