2016-01-19 11 views
6

Recentemente ho risolto un problema con l'interrogazione delle tabelle di unione delle relazioni ManyToMany, la soluzione era uguale a questa answer e mi chiedevo come funziona. Diciamo che ho un semplice ManyToMany rapporto tra groups e team, ci sarà un groups_team tabelle che verranno automaticamente creati quiCome funziona inner join su una relazione molti-a-molti utilizzando Doctrine e Symfony2

gruppi entità

/** 
* 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 :) 

entità squadra

/** 
* 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] 

al fine per ottenere tutte le squadre in un gruppo avrei dovuto interrogare la tabella groups_team. avrei direttamente interrogato la tabella solo in mysql ma in symfony devo fare questo

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

Qualcuno può spiegarmi come la innerJoin funziona e cosa è il concetto alla base di questo, forse un paio di documentazione per conoscere questo. c'è un modo migliore per farlo con symfony e la dottrina.

risposta

5

L'utilizzo di ManyToMany tra 2 entità implica una terza tabella generalmente chiamata tabella di giunzione in questo tipo di relazione quando si crea una DQL (doctrine query) la docenza si unisce automaticamente alla tabella di giunzione in base alla natura della relazione definita come annotazione considerando la query

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

si stanno unendo Team ente con Group entità innerJoin('o.group') parte o è l'alias per l'entità della squadra e o.group si riferisce a proprietà definita in Team soggetto nominato come group.

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

che ha un ManyToMany un'annotazione definita per questo tipo di relazione dottrina si unisce alla tua tavola prima squadra con la tabella di giunzione e poi si unisce la vostra tabella di collegamento con la tabella gruppi e SQL risultante sarà qualcosa di simile a

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 

Un'altra cosa correlata al tuo modo di ottenere squadra per ogni gruppo, puoi minimizzare il tuo codice escludendo la parte createQueryBuilder all'interno del ciclo, una volta definita la proprietà team come ArrayCollection i.e $this->team = new ArrayCollection(); su ogni oggetto del gruppo si otterranno raccolte di squadre associate a quel particolare gruppo chiamando la funzione getTeam() su un oggetto gruppo simile al codice sottostante.

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

grazie, questo ha ridotto il mio codice, e mi ha iniziato a pensare a un codice più snello. Questo ha risposto alla mia domanda al 100%. SO è una grande piattaforma. +1 –

0

Immagino che sia letteralmente selezionare l'istruzione con INNER JOIN usando le colonne chiave definite entity class come mappedBy o inversedBy. Perché non si ha un aspetto del registro di doctrine e si vede che cosa è composto il sql nativo?

How to get Doctrine to log queries in Symfony2 (StackOverflow)

http://vvv.tobiassjosten.net/symfony/logging-doctrine-queries-in-symfony2/ (alcuni esempi di codice)

Non so la tua storia utente alla base di questo, ma ho anche sentito dire che si consiglia di utilizzare uno a molti invece di molti a molti, a meno che non vi sia una forte ragione per farlo, poiché la maggior parte dei casi può essere gestita da uno a molti riconsiderando i modelli.

+0

Ciao grazie per la risposta, sì, ho considerato 'OneToMany' -' ManyToOne' al posto di 'ManyToMany'. ma, un grosso MA, non è esattamente lo stesso, hai un lato "uno" per "OneToMany - ManyToOne" che significa che dobbiamo usare un ciclo per inserire i record, e questo non è solo disordinato, ma coinvolge anche un sacco di codice personalizzato (suggerimento: implica l'uso di 'clone' o' detach() '_shivers! _) per fare una semplice operazione CRUD. e quindi il buon vecchio 'ManyToMany'. –