Doctrine:复杂的选择与两个ManyToMany关系

时间:2013-01-28 11:02:19

标签: doctrine-orm many-to-many query-builder

我需要在问题跟踪系统的表格中查询一些问题,以便通过复杂的条件限制此查询:

问题(实体)按类别(另一个实体)分组。 Persons(Entity)是多个角色的成员(第四个Entity),这是一个ManyToMany关系。最后,角色可以访问一个或多个类别,这是第二个ManyToMany关系。

<?php

/**
 * @Entity
 * @Table(name="issue")
 */
class Issue
{
    /**
     * @ManyToOne(targetEntity="Category", fetch="EAGER")
     * @JoinColumn(name="category", referencedColumnName="id", onDelete="RESTRICT", nullable=false)
     */
    private $category;
    …
}

/**
 * @Entity
 * @Table(name="category")
 */
class Category
{
    /**
     * @ManyToMany(targetEntity="Role", mappedBy="categories")
     */
    private $roles;
    …
}

/**
 * @Entity
 * @Table(name="role")
 */
class Role
{
    /**
     * @ManyToMany(targetEntity="Person", mappedBy="roles")
     */
    private $persons;

    /**
     * @ManyToMany(targetEntity="Category", inversedBy="roles")
     * @JoinTable(name="role_has_access_on_category",
     *  joinColumns={@JoinColumn(name="role_id", referencedColumnName="id")},
     *  inverseJoinColumns={@JoinColumn(name="category_id", referencedColumnName="id")}
     * )
     */
    private $categories;
    …
}

/**
 * @Entity
 * @Table(name="person")
 */
class Person
{   
    /**
     * @ManyToMany(targetEntity="Role", inversedBy="persons")
     * @JoinTable(name="person_is_member_of_role",
     *  joinColumns={@JoinColumn(name="person_id", referencedColumnName="id")},
     *  inverseJoinColumns={@JoinColumn(name="role_id", referencedColumnName="id")})
     */
    private $roles;
    …
}

我离开了除了关系之外的所有字段,当然还有主键和更多列...

我想检索属于具有给定主键的人可通过其所属角色访问的类别的所有问题。

首先,我开始尝试如何查询ManyToMany关系,因此下面的代码与我的目标不太相似。 我终于找到了如何获取查询来检索一个ManyToMany关系的另一面,所以我已经可以获得一个人所属的角色了。但是此查询不会获取角色可以访问的类别。

$qb = $this->em->createQueryBuilder();
$qb->select('person')
   ->addSelect('role')
   ->addSelect('category')
   ->from('Person', 'person')
   ->innerJoin('person.roles', 'role')
   ->innerJoin('role.categories', 'category');

$result = $qb->getQuery()->getResult();

$ result包含具有所有相关角色的人员数据,但是包含一组空白而不是实体。最后的查询当然是从问题方面开始的,但是现在我只想通过另一方......

所以现在我想知道我是否必须接受所有角色并循环遍历它们以获取所有类别。是不是更容易理论?

顺便说一句,这就是我要使用的SQL:

SELECT issue.* FROM person AS p, person_is_member_of_role AS pim, role_has_access_on_category AS rha, issue
WHERE
    p.id = pim.person_id AND
    pim.role_id = rha.role_id AND
    rha.category_id = todo.category AND
    p.id = ?;

我希望这一切都能以某种方式表明,否则我会修改我的问题......

1 个答案:

答案 0 :(得分:0)

通过尝试将所有连接条件放在WHERE子句中,使您过于复杂。

如果我正确理解了这个问题,查询将如下所示:

SELECT
    i
FROM
    Issue i
JOIN
    i.category c
JOIN
    c.roles r
JOIN
    r.persons p
WHERE
    p.id = :personId

QueryBuilder API中翻译:

$qb = $entityManager->createQueryBuilder();
$issues = $qb
    ->select('i')
    ->from('Issue', 'i')
    ->innerJoin('i.category', 'c')
    ->innerJoin('c.roles', 'r')
    ->innerJoin('r.persons', 'p')
    ->andWhere($qb->expr()->eq('p.id', ':personId'))
    ->setParameter('personId', $personId)
    ->getQuery()
    ->getResult();

另外,如果没有充分的理由使用它,请考虑避免使用QueryBuilder。毕竟,它只是一个字符串构建器。