【问题标题】:How does inner join work on a many-to-many relationship using Doctrine and Symfony2内部连接如何使用 Doctrine 和 Symfony2 处理多对多关系
【发布时间】:2016-04-24 18:58:01
【问题描述】:

我最近解决了查询ManyToMany 关系连接表的问题,解决方案与answer 相同,想知道它是如何工作的。 假设我在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 和教义来做到这一点。

【问题讨论】:

    标签: php mysql symfony doctrine-orm doctrine


    【解决方案1】:

    我猜它实际上是带有 INNER JOIN 的 select 语句,使用键列将实体类定义为 mappedBy 或 inversedBy。 不如看一下学说日志,看看原生sql是怎么组成的?

    How to get Doctrine to log queries in Symfony2(堆栈溢出)

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

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

    【讨论】:

    • 嗨,感谢您的回答,是的,我确实考虑过 OneToMany - ManyToOne 代替 ManyToMany。但是,一个很大的但是,它肯定不一样,OneToMany - ManyToOne 有一个“单”的一面,这意味着我们必须使用循环来插入记录,这不仅是混乱的,而且还涉及很多自定义代码(提示:它涉及使用 clonedetach() shivers!)来执行简单的 CRUD 操作。因此,好的 ol ManyToMany.
    【解决方案2】:

    在 2 个实体之间使用 ManyToMany 涉及到在这种类型的关系中通常称为联结表的第三个表,当您构建 DQL(学说查询)原则时,会根据您定义为注释的关系的性质自动连接联结表所以考虑你的查询

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

    您将加入Team 实体和innerJoin('o.group') 部分中的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 部分来最小化您的代码,一旦您将团队属性定义为ArrayCollection$this-&gt;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>";
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2014-09-14
      • 2014-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-11
      • 2012-02-20
      • 1970-01-01
      相关资源
      最近更新 更多