Activité : Doctrine et les relations [possibilité] - SimplonReunion/developpeur-web GitHub Wiki
Rappel
Une des solutions
Tout d'abord on crée les entités Equipe,Joueur et Match et leurs relations.
Entité Joueur
On commence par l'entité Joueur :
<?php
//src/SimplonReunion/Playground/Entity
namespace SimplonReunion\PlaygroundBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Joueur
*
* @ORM\Table(name="joueur")
* @ORM\Entity(repositoryClass="SimplonReunion\PlaygroundBundle\Repository\JoueurRepository")
*/
class Joueur
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="nom", type="string", length=255)
*/
private $nom;
/**
* @var string
*
* @ORM\Column(name="prenom", type="string", length=255)
*/
private $prenom;
/**
* @ORM\ManyToOne(targetEntity="Equipe", inversedBy="joueurs")
*/
private $equipe;
/**
* @ORM\Column(name="numero_joueur", type="integer")
*/
private $numeroJoueur;
public function getNumeroJoueur(){
return $this->numeroJoueur;
}
public function setNumeroJoueur($numeroJoueur){
$this->numeroJoueur = $numeroJoueur;
return $this;
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set nom
*
* @param string $nom
*
* @return Joueur
*/
public function setNom($nom)
{
$this->nom = $nom;
return $this;
}
/**
* Get nom
*
* @return string
*/
public function getNom()
{
return $this->nom;
}
/**
* Set prenom
*
* @param string $prenom
*
* @return Joueur
*/
public function setPrenom($prenom)
{
$this->prenom = $prenom;
return $this;
}
/**
* Get prenom
*
* @return string
*/
public function getPrenom()
{
return $this->prenom;
}
/**
* Set equipe
*
* @param \SimplonReunion\PlaygroundBundle\Entity\Equipe $equipe
*
* @return Joueur
*/
public function setEquipe(\SimplonReunion\PlaygroundBundle\Entity\Equipe $equipe = null)
{
$this->equipe = $equipe;
return $this;
}
/**
* Get equipe
*
* @return \SimplonReunion\PlaygroundBundle\Entity\Equipe
*/
public function getEquipe()
{
return $this->equipe;
}
}
On sait que l'on doit avoir une relation entre Joueur et Equipe de type ManyToOne. Plusieurs joueurs font parti que d'une seule équipe et une équipe peut avoir un ou plusieurs joueurs.
Pour que Doctrine crée cette relation il faut le lui dire, d'où l'utilisation de l'annotation au-dessus de la propriété $equipe
:
/**
* @ORM\ManyToOne(targetEntity="Equipe", inversedBy="joueurs")
*/
private $equipe;
Entité Equipe
On créé l'entité Equipe :
<?php
namespace SimplonReunion\PlaygroundBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Equipe
*
* @ORM\Table(name="equipe")
* @ORM\Entity(repositoryClass="SimplonReunion\PlaygroundBundle\Repository\EquipeRepository")
*/
class Equipe
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="nom", type="string", length=255)
*/
private $nom;
/**
* @ORM\OneToMany(targetEntity="Joueur", mappedBy="equipe",cascade={"persist"})
*/
private $joueurs;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set nom
*
* @param string $nom
*
* @return Equipe
*/
public function setNom($nom)
{
$this->nom = $nom;
return $this;
}
/**
* Get nom
*
* @return string
*/
public function getNom()
{
return $this->nom;
}
/**
* Constructor
*/
public function __construct()
{
$this->joueurs = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add joueur
*
* @param \SimplonReunion\PlaygroundBundle\Entity\Joueur $joueur
*
* @return Equipe
*/
public function addJoueur(\SimplonReunion\PlaygroundBundle\Entity\Joueur $joueur)
{
$this->joueurs[] = $joueur;
return $this;
}
/**
* Remove joueur
*
* @param \SimplonReunion\PlaygroundBundle\Entity\Joueur $joueur
*/
public function removeJoueur(\SimplonReunion\PlaygroundBundle\Entity\Joueur $joueur)
{
$this->joueurs->removeElement($joueur);
}
/**
* Get joueurs
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getJoueurs()
{
return $this->joueurs;
}
}
De même, on sait que la relation qui lie Equipe à Joueur est de type OneToMany. Une équipe peut avoir plusieurs Joueur, d'où l'annotation sur la propriété joueurs
/**
* @ORM\OneToMany(targetEntity="Joueur", mappedBy="equipe")
*/
private $joueurs;
Comme l'équipe peut avoir plusieurs joueurs vous vous doutez bien que joueurs
ressemble plus à un tableau. J'écris "ressemble" car plus exactement c'est plutôt un ArrayCollection. Retenez juste que c'est un tableau amélioré pour Doctrine.
Par conséquent, lors de la construction de l'entité (lorsqu'on fait un new
) il le faut définir explicitement. Dans le constructeur de Equipe on ajoutera donc :
/**
* Constructor
*/
public function __construct()
{
$this->joueurs = new \Doctrine\Common\Collections\ArrayCollection();
}
Entité Match
Il ne reste plus que l'entité Match à créer
<?php
namespace SimplonReunion\PlaygroundBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Matchs
*
* @ORM\Table(name="matchs")
* @ORM\Entity(repositoryClass="SimplonReunion\PlaygroundBundle\Repository\MatchsRepository")
*/
class Matchs
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="lieu", type="string", length=255)
*/
private $lieu;
/**
* @ORM\ManyToMany(targetEntity="Equipe",mappedBy="matchs",cascade={"persist"})
*/
private $equipes;
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set lieu
*
* @param string $lieu
*
* @return Matchs
*/
public function setLieu($lieu)
{
$this->lieu = $lieu;
return $this;
}
/**
* Get lieu
*
* @return string
*/
public function getLieu()
{
return $this->lieu;
}
/**
* Constructor
*/
public function __construct()
{
$this->equipes = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* Add equipe
*
* @param \SimplonReunion\PlaygroundBundle\Entity\Equipe $equipe
*
* @return Matchs
*/
public function addEquipe(\SimplonReunion\PlaygroundBundle\Entity\Equipe $equipe)
{
$this->equipes[] = $equipe;
return $this;
}
/**
* Remove equipe
*
* @param \SimplonReunion\PlaygroundBundle\Entity\Equipe $equipe
*/
public function removeEquipe(\SimplonReunion\PlaygroundBundle\Entity\Equipe $equipe)
{
$this->equipes->removeElement($equipe);
}
/**
* Get equipes
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getEquipes()
{
return $this->equipes;
}
}
Un match peut se faire en plusieurs équipes et les équipes peuvent faire plusieurs matchs. C'est donc une relation de plusieurs à plusieurs : ManyToMany.
/**
* @ORM\ManyToMany(targetEntity="Equipe",mappedBy="matchs",cascade={"persist"})
*/
private $equipes;
Le match s'attends à avoir plusieurs équipes. On va encore retrouver un ArrayCollection initialiser dans le constructeur de notre entité.
/**
* Constructor
*/
public function __construct()
{
$this->equipes = new \Doctrine\Common\Collections\ArrayCollection();
}
Nos entités sont créés. N'oubliez pas de mettre à jour le schéma de la base de données :
bin/console doctrine:schema:update --force
Si vous avez un doute sur la validité des annotations de Doctrine vous pouvez utiliser la commande :
bin/console doctrine:schema:validate
Insérer dans la base
On crée un controller JeuController
qui va gérer la création des 12 joueurs, 2 équipes et 1 match. On va tout mettre dans la même action.
<?php
namespace SimplonReunion\PlaygroundBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use SimplonReunion\PlaygroundBundle\Entity\Joueur;
use SimplonReunion\PlaygroundBundle\Entity\Matchs;
use SimplonReunion\PlaygroundBundle\Entity\Equipe;
class JeuController extends Controller
{
/**
* @Route("/jeu/massif")
*/
public function massifAction()
{
$joueur1 = $this->creerJoueur('Fleury', 'Antoine', 5);
$joueur2 = $this->creerJoueur('ZUIDBERG', 'Chris', 7);
$joueur3 = $this->creerJoueur('HENNO', 'Hubert', 8);
$joueur4 = $this->creerJoueur('SIECKER', 'Julien', 15);
$joueur5 = $this->creerJoueur('LOMBARD', 'Vincent', 1);
$joueur6 = $this->creerJoueur('BOEL', 'Yves Alexandre', 3);
$joueur7 = $this->creerJoueur('FREDERIC', 'Malick', 2);
$joueur8 = $this->creerJoueur('JUHKAMI', 'Martti', 10);
$joueur9 = $this->creerJoueur('KOPRIVICA', 'Lazar', 9);
$joueur10 = $this->creerJoueur('NEVOT', 'Tanguy', 15);
$joueur11 = $this->creerJoueur('RAGONDET', 'Vincent', 1);
$joueur12 = $this->creerJoueur('AH-KONG', 'Rodney Ken', 3);
$equipe1 = new Equipe();
$equipe1->setNom('Tour Volley-Ball');
$equipe2 = new Equipe();
$equipe2->setNom('Rennes Volley-Ball');
$equipe1->addJoueur($joueur1)
->addJoueur($joueur2)
->addJoueur($joueur3)
->addJoueur($joueur4)
->addJoueur($joueur5)
->addJoueur($joueur6)
;
$equipe2->addJoueur($joueur7)
->addJoueur($joueur8)
->addJoueur($joueur9)
->addJoueur($joueur10)
->addJoueur($joueur11)
->addJoueur($joueur12)
;
$match = new Matchs();
$match->setLieu('Paris');
$match->addEquipe($equipe1)
->addEquipe($equipe2);
$em = $this->getDoctrine()->getManager();
//On peut persist uniquement match car dans mes relations on a explicitement
//demandé que les persist soient fait en cascade
//Donc quand on persist un Match, comme c'est en cascade, ça va aussi persist Equipe
//et Joueur
$em->persist($match);
$em->flush();
return $this->render('SimplonReunionPlaygroundBundle:Jeu:massif.html.twig', array(
// ...
));
}
/**
* Créer un joueur.
*
* @param string $nom
* @param string $prenom
* @param string $numeroJoueur
*
* @return Joueur
*/
protected function creerJoueur($nom, $prenom, $numeroJoueur)
{
$joueur = new Joueur();
$joueur->setNom($nom)
->setPrenom($prenom)
->setNumeroJoueur($numeroJoueur)
;
return $joueur;
}
}
Comme vous avez pu le remarquer, on ne fait qu'un seul persist $em->persist($match);
c'est parce que sur mes relation j'ai défini des persist
en cascade.
//Equipe
//...
/**
* @ORM\OneToMany(targetEntity="Joueur", mappedBy="equipe",cascade={"persist"})
*/
private $joueurs;
//...
//Match
//...
/**
* @ORM\ManyToMany(targetEntity="Equipe",mappedBy="matchs",cascade={"persist"})
*/
private $equipes;
//...
Aller plus loin
La relation entre Joueur
et Equipe
est une relation bi-directionnelle. À partir d'Equipe
on peut accéder aux Joueur
(grâce à la propriété joueurs
) et à partir de Joueur
on peut accéder à Equipe
(grâce à la propriété equipe
).
Par contre, la relation entre Match
et Equipe
est unidirectionnel. Depuis Match
on peut accéder aux Equipe
mais pas l'inverse.
Vous pouvez tout à fait la rendre bidirectionnelle.