2016-01-19 11 views
6

最近、ManyToManyリレーションシップジョインテーブルをクエリする際に問題が発生しました。解決方法はanswerと同じでした。 は私がgroupsteam間の単純なManyToManyの関係は、自動的に順番にここDoctrineとSymfony2を使用した多対多リレーションシップの内部結合の仕組み

グループエンティティ

/** 
* 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テーブルがあるだろう持って言うことができますグループ内のすべてのチームを取得するには、groups_team table.iを照会する必要があります。これは、mysqlでテーブルを直接照会しただけですが、 symfonyは私がinnerJoinが動作しているか、この

 $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>"; 
      } 
     } 

は、誰かが私に説明できなければならないと、この背後にある考え方、これについて学ぶために、多分、いくつかのドキュメントは何ですか。 symfonyと教義でこれを行うより良い方法があります。

答えて

5

2エンティティ間でManyToManyを使用すると、DQL(doctrineクエリ)を作成するときに一般的に接合テーブルと呼ばれる第3のテーブルが使用されます。doctrineは、アノテーションとして定義したリレーションの性質に応じてジャンクションテーブルを自動的に結合します。

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

あなたはinnerJoin('o.group')一部oGroupエンティティとTeamエンティティに参加しているクエリを考慮すると、チームのエンティティの別名であるとo.groupgroupとして名前Teamエンティティで定義されたプロパティを参照します。

関係の教義のこのタイプのために定義された 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 
ようになります持って
/** 
* @ORM\ManyToMany(targetEntity="Groups", mappedBy="team") 
*/ 
protected $group; 


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

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

ありがとう、これは私のコードを減らし、より合理的なコードを考え直すために私を始めました。これは私の質問に100%答えました。 SOは素晴らしいプラットフォームです。 +1 –

0

私は、エンティティクラスをmappedByまたはinversedByとして定義したキー列を使用して、INNER JOINを使って文字通りSELECTステートメントと思っています。 教義ログを見て、ネイティブSQLが何を構成しているのか見てみませんか?

How to get Doctrine to log queries in Symfony2(stackoverflowの)

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

私はこの背後にあるユーザーの話を知らないが、私はまた、多くのではなく、多くの関係に1を使用することが推奨されていることを聞きました大部分のケースはモデルを再考することによって1対多の方法で処理できるため、そうする強い理由がない限り、多くの人に伝えます。

+0

やあおかげで、はい私は 'OneToMany'を検討しました。しかし、それほど変わらず、あなたはOneToMany - ManyToOneに「片側」を持っています。これは、レコードを挿入するためにループを使用しなければならないことを意味します。これは面倒ではありませんが、簡単なCRUD操作を行うためにカスタムコードがたくさんあります(ヒント: 'clone'や' detach() '_shivers!_を使って)。それゆえ良いMany'ManyToMany。 –

関連する問題