内部连接如何使用 Doctrine 和 Symfony2 处理多对多关系


How does inner join work on a many-to-many relationship using Doctrine and Symfony2

我最近解决了查询ManyToMany关系连接表的问题,解决方案与此答案相同,并且想知道它是如何工作的。假设我在groupsteam之间有一个简单的ManyToMany关系,这里会自动创建一个groups_team

组实体

/**
 * Groups
 *
 * @ORM'Table(name="groups")
 * @ORM'Entity(repositoryClass="AppBundle'Model'Repository'GroupsRepository")
 */
class Groups {
    /**
     * @ORM'ManyToMany(targetEntity="Team", inversedBy="group")
     */
    protected $team;
    public function __construct() {
        $this->team = new ArrayCollection();
    }
    /**
     * @var int
     *
     * @ORM'Column(name="id", type="integer")
     * @ORM'Id
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string
     *
     * @ORM'Column(name="groupname", type="string", length=255)
     */
    private $groupname;
    //obligatory getters and setters :)

团队实体

/**
 * Team
 * 
 * @ORM'Table(name="team")
 * @ORM'Entity(repositoryClass="AppBundle'Model'Repository'TeamRepository")
 */
class Team {
    /**
     * @ORM'ManyToMany(targetEntity="Groups", mappedBy="team")
     */
    protected $group;
    public function __construct(){
        $this->group = new ArrayCollection();
    }
    /**
     * @var int
     *
     * @ORM'Column(name="id", type="integer")
     * @ORM'Id
     * @ORM'GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @var string
     *
     * @ORM'Column(name="teamname", type="string", length=255)
     */
    private $team;
    //[setters and getters here]

为了获得组中的所有团队,我必须查询groups_team表.我会直接在MySQL中查询表,但在Symfony中我必须这样做

      $groups = $em->getRepository("AppBundle'Model'Entity'Groups")->findBy(array('tournament' => $tournament->getId()));
        //get all teams with group id in groups_team table
        foreach ($groups as $group) {
            $teamsingroup = $em->getRepository("AppBundle'Model'Entity'Team")->createQueryBuilder('o')
                    ->innerJoin('o.group', 't')
                    ->where('t.id = :group_id')
                    ->setParameter('group_id', $group->getId())
                    ->getQuery()->getResult();
            echo "</b>".$group->getGroupname()."</b></br>";
            foreach ($teamsingroup as $teamingroup) {
                echo $teamingroup->getTeam()."</br>";
            }
        }

有人可以向我解释innerJoin是如何工作的以及这背后的概念是什么,也许有一些文档可以了解这一点。 有没有更好的方法来用Symfony和Doctrine来做到这一点。

2 个实体之间使用ManyToMany涉及第三个表,通常在此类关系中称为联结表,当您构建 DQL(学说查询)时,学说会根据您定义为注释的关系的性质自动联接联结表

$teamsingroup = $em->getRepository("AppBundle'Model'Entity'Team")
                    ->createQueryBuilder('o')
                    ->innerJoin('o.group', 't')

您正在Team实体与Group实体联接innerJoin('o.group')部分中o是团队实体的别名,o.group是指Team名为 group 的实体中定义的属性。

/**
 * @ORM'ManyToMany(targetEntity="Groups", mappedBy="team")
 */
protected $group;

它为这种类型的关系原则定义了ManyToMany注释,首先将团队表与联结表连接起来,然后将联结表与组表连接起来,生成的 SQL 将类似于

SELECT t.*
FROM teams t
INNER JOIN junction_table jt ON(t.id = jt.team_id)
INNER JOIN groups g ON(g.id = jt.group_id)
WHERE g.id = @group_id

另一件事与你为每个组获取团队的方式有关,你可以通过在循环中排除createQueryBuilder部分来最小化你的代码,一旦你定义了 teams 属性ArrayCollection即在每个组对象上$this->team = new ArrayCollection();,你将获得与该特定组关联的团队集合通过在组对象上调用类似于以下代码的函数getTeam()

foreach ($groups as $group) {
    $teamsingroup = $group->getTeam();
    echo "</b>".$group->getGroupname()."</b></br>";
    foreach ($teamsingroup as $teamingroup) {
        echo $teamingroup->getTeam()."</br>";
    }
}

我想它实际上是带有 INNER JOIN 的选择语句,使用键列将实体类定义为 mappedBy 或 inversedBy。你为什么不看看教义日志,看看原生SQL是由什么组成的?

如何让 Doctrine 在 Symfony2 中记录查询(stackoverflow)

http://vvv.tobiassjosten.net/symfony/logging-doctrine-queries-in-symfony2/(一些代码示例)

我不知道这背后的用户故事,但我也听说建议使用一对多关系而不是多对多,除非有充分的理由这样做,因为大多数情况可以通过重新考虑模型由一对多处理。