web-dev-qa-db-ja.com

Doctrine and Symfony2を使用して、内部結合は多対多の関係でどのように機能しますか

最近、ManyToMany関係結合テーブルのクエリに関する問題を解決しました。解決策はこれと同じでした answer で、どのように機能するのか疑問に思いました。 ManyToManygroupsの間に単純なteamの関係があるとすると、ここに自動的に作成される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と教義でこれを行うためのより良い方法はありますか?.

2つのエンティティ間でManyToManyを使用すると、DQL(doctrineクエリ)を構築するときに、このタイプのリレーションで一般にジャンクションテーブルと呼ばれる3番目のテーブルが必要になりますdoctrineは、に応じてジャンクションテーブルを自動的に結合しますアノテーションとして定義した関係の性質なので、クエリを検討します

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

innerJoin('o.group')パートでTeamエンティティをGroupエンティティと結合しています。oはチームエンティティのエイリアスであり、_o.group_はで定義されたプロパティを参照します。 Teamという名前のgroupエンティティ。

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

このタイプの関係に対してManyToManyアノテーションが定義されているdoctrine最初にチームテーブルをジャンクションテーブルと結合し、次にジャンクションテーブルをグループテーブルと結合すると、結果の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
_

各グループのチームを取得する方法に関連するもう1つのことは、チームプロパティをcreateQueryBuilder、つまり$this->team = new ArrayCollection(); onとして定義したら、ループ内のArrayCollection部分を除外することでコードを最小限に抑えることができます。各グループオブジェクトは、以下のコードのようにグループオブジェクトでgetTeam()関数を呼び出すことにより、その特定のグループに関連付けられたチームのコレクションを取得します。

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

エンティティクラスをmappedByまたはinversedByとして定義されたキー列を使用して、文字通りINNERJOINを使用したselectステートメントだと思います。 doctrine logを見て、ネイティブSQLが何で構成されているかを確認してみませんか?

Symfony2でクエリをログに記録するためのDoctrineの取得方法 (stackoverflow)

http://vvv.tobiassjosten.net/symfony/logging-doctrine-queries-in-symfony2/ (いくつかのコード例)

この背後にあるユーザーストーリーはわかりませんが、ほとんどの場合は1人で処理できるため、強い理由がない限り、多対多ではなく1対多の関係を使用することをお勧めします。モデルを再考することによって多くの人に。

0
Motoroller