Tuto Symfony3 : Les relations entre les entités

Dans le deuxième tutoriel Symfony3 nous avons généré les entités mais chacune est indépendante des autres.Nous n'avons pas encore évoqué le sujet de l'interaction entre les entités.

L'ORM Doctrine va s'occuper de ce que nous avions eu l'habitude de faire manuellement. Avant, en créant des tables dans la base de donnés on intervient directement au niveau de phpmyadmin et on crée les relations en ajoutant un id comme une clé étrangère (foreign key) qui fait référence à une autre table .Par exemple si on a une table livre et une table auteur, pour faire référence à l'auteur d'un certain livre on doit créer un champ "id_auteur" .Maintenant grâce à l'ORM on ne va plus toucher phpmyadmin ,on contrôle tout à partir de nos classes entité ,Doctirne comprend ce qu'il doit faire.

Notion Propriétaire et inverse
C'est une notion purement technique.Dans l'exemple de livre et auteur vous remarquez que c'est la table livre qui possède une référence(foreign-key) de la table auteur donc Livre est l'entité propriétaire et Auteur est dite Inverse.


Unidirectionnelle ou bidirectionnelle
C'est une question de sens.Dans le cas d'un seul sens on modifie juste le code de l'entité propriétaire .On n'ajoute ren à l'entité inverse .Dans ce cas l'expression propriétaire->getInverse() est valide mais le contraire est invalide .Par exemple dans le cas de Livre et Auteur on peut avoir $livre->getAuteur() mais on ne pas avoir $auteur->getLivres() .Par contre si la relation est bidirectionnelle on peut bien avoir les deux expressions valides.
Dans cet article nous nous intéressons seulement des relations unidirectionnelles pour simplifier les choses.Pour des cas plus particuliers vous pouvez trouver des documentations plus complètes .Mais pour le moment essayez de bien comprendre le principe de base avant de passer à des choses plus compliquées.

Les types de relations entre les entités

OneToOne

Restons dans l'exemple de livres si un livre possède une seule couverture et une couverture ne peut présenter qu'un seul livre c'est le cas d'une relation OneToOne.

Si l'entité Livre est la propriétaire donc on définit cette relation au niveau de la classe LivreEntity de la façon suivante:


  3 
class Livre
  4 
{
  5 
 /**
  6 
   * @ORM\OneToOne(targetEntity="Couverture")
  7 
   * @JoinColumn(name="couverture_id",referencedColumnName="id",
  8 
     nullable=true,onDelete="CASCADE")
  9 
   */
 10 
  private $couverture;
 11 
    //
 12 
}

Remarques:
onDelete="cascade" est utilisé pour synchroniser la suppression ,c'est à dire si on supprime un livre sa couverture sera automatiquement supprimée.


@JoinColumn et une option qui sert à préciser quel champs de l'entité Couverture sera la référence, par défaut c'est l'id et sera nommé id_couverture au niveau de la BD .L'utilisation de @joinColumn n'est pas obligatoire car ces paramétres sont par défaut sauf si on veut utiliser un autre champ comme référence dans ce cas il faut le définir.



ManyToOne

Prenons l'exemple d'une entité Voiture et d'une entité Marque plusieurs voitures peuvent avoir la même marque donc c'est une relation ManyToOne.

 2 
class Voiture
 3 
{
 4 
  /**
 5 
   * @ORM\ManyToOne(targetEntity="Marque")
 6 
   */
 7 
  private $marque;
 8 
    //
 9 
}


ManyToMany

On va prendre un exemple du projet FoodCorner.La relation entre l'entité Commande et l'entité Plat est une relation ManyToMany .Lors d'une commande un client peut commander un plat pour plusieurs personnes.Prenons l'exemple d'une pizza , un client n'est pas obligé de commander une seule pizza il peut commander plusieurs pizzas selon ses besoins.Pour définir la relation ManyToOne il ya deux possibilités.

1/Definir une relation ManyToMany dans la classe Commande.php


  3 
class Commande
  4 
{
  5 
//...
  6 
 
  7 
 /**
  8 
   * @ORM\ManyToMany(targetEntity="Plat")
  9 
   */
 10 
  private $plats;
 11 
 
 12 
  //....
 13 
}

2/Utiliser la relation ManyToMany avec attribut


Le client doit préciser le nombre  du coup nous avons besoin d'un attribut nombre .Les deux entités Plat et Commande  n'ont pas cet attribut , nous allons donc créer une entité intermédiaire CommandePlat pour la relation et lui ajouter cet attribut nombre.ce type de relation est dit ManyToMany avec attribut.


Classe CommandePlat.php


  1 
<?php
  2 
 
  3 
namespace RestoBundle\Entity;
  4 
 
  5 
use Doctrine\ORM\Mapping as ORM;
  6 
 
  7 
/**
  8 
* CommandePlat
  9 
 *
 10 
 * @ORM\Table(name="commande_plat")
 11 
 * @ORM\Entity(repositoryClass="RestoBundle\Repository\CommandePlatRepository")
 12 
 */
 13 
class CommandePlat
 14 
{
 15 
    /**
 16 
     * @var int
 17 
     *
 18 
     * @ORM\Column(name="id", type="integer")
 19 
     * @ORM\Id
 20 
     * @ORM\GeneratedValue(strategy="AUTO")
 21 
     */
 22 
    private $id;
 23 
 
 24 
    /**
 25 
     * @var int
 26 
     *
 27 
     * @ORM\Column(name="nbr", type="integer")
 28 
     */
 29 
    private $nbr;


 31 
 
 32 
    /**
 33 
     * Get id
 34 
     *
 35 
     * @return int
 36 
     */
 37 
    public function getId()
 38 
    {
 39 
        return $this->id;
 40 
    }
 41 
 
 42 
    /**
 43 
     * Set nbr
 44 
     *
 45 
     * @param integer $nbr
 46 
     *
 47 
     * @return CommandePlat
 48 
     */
 49 
    public function setNbr($nbr)
 50 
    {
 51 
        $this->nbr = $nbr;
 52 
 
 53 
        return $this;
 54 
    }
 55 
 
 56 
    /**
 57 
     * Get nbr
 58 
     *
 59 
     * @return int
 60 
     */
 61 
    public function getNbr()
 62 
    {
 63 
        return $this->nbr;
 64 
    }
 65 
}
 66 
 


Ensuite il faut ajouter les attributs plat et commande à cette entité .Il faut aussi définir deux relations de type ManyToOne entre cette entité et les entités Commande et Plat.


 32 
/**
 33 
     * @ORM\ManyToOne(targetEntity="Commande")
 34 
     * @ORM\JoinColumn(nullable=false)
 35 
     */
 36 
    private $commande;
 37 

 38 
    /**
 39 
     * @ORM\ManyToOne(targetEntity="Plat")
 40 
     * @ORM\JoinColumn(nullable=false)
 41 
     */
 42 
    private $palt;


De la même façon nous allons créer une relation ManyToMany entre l'entité Commande et les entités Entree , Salade et Dessert.Enfin nous aurons donc quatre nouvelles entités:

CommandePlat.php
CommandeSalade.php
CommandeEntree.php 
CommandeDessert.php

Ajouter les getters et les setters



Mettre à jour la base de donnes 




Si vous ouvrez phpmyadmin vous allez remarquer la création de nouvelles tables:




Voilà donc nous avons vu les notions de bases de la relation entre les entités.Nous avons défini des relations entre les entités de notre projet .Dans le prochain tutoriel nous allons voir les templates twig , les liens et la redirection.

Commentaires