Relation OneToMany et ManyToOne des entités Doctrine


Suite du tutoriel sur la création des relations entre entités pour leur persistance en base de données avec Doctrine.

Pour les précédent tutoriels :

Dans cette partie nous traiterons de OneToMany et sa réciproque ManyToOne

Shchéma merise d'une relation OneToMany ManyToOneUne région possède zéro ou plusieurs départements.
Un département appartient à une et une seul région.

Voici le SQL correspondant :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
TABLE `Region` (
  `idRegion` bigint(20) NOT NULL AUTO_INCREMENT,
  `nom` varchar(60) DEFAULT NULL,
  PRIMARY KEY (`idRegion`));
TABLE `Departement` (
  `idDepartement` INT NOT NULL ,
  `nom` VARCHAR(60) NULL ,
  `Region_idRegion` INT NOT NULL ,
  PRIMARY KEY (`idDepartement`, `Region_idRegion`) ,
  INDEX `fk_Departement_Region` (`Region_idRegion` ASC) ,
  CONSTRAINT `fk_Departement_Region`
    FOREIGN KEY (`Region_idRegion` )
    REFERENCES `Region` (`idRegion` ) ) ;

Voici les entités correspondante :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
namespace WaldoRelationBundleEntity;
use DoctrineORMMapping as ORM;
use DoctrineCommonCollectionsArrayCollection;
/**
 * @ORMTable(name="Region")
 * @ORMEntity
 */
class Region
{
    /**
     * @var decimal $identifiantRegion
     *
     * @ORMColumn(name="idRegion", type="bigint", nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy="IDENTITY")
     */
    private $identifiantRegion;
    /**
     * @var text $nom
     *
     * @ORMColumn(name="nom", type="string", length=60, nullable=true)
     */
    private $nom;
     /**
     * @var ArrayCollection $departements
     *
     * @ORMOneToMany(targetEntity="Departement", mappedBy="region", cascade={"persist", "remove", "merge"})
     */
    private $departements;
    /**
     * @return decimal $identifiantRegion
     */
    public function getIdentifiantRegion()
    {
        return $this->identifiantRegion;
    }
    /**
     * @param text $nom
     */
    public function setNom($nom)
    {
        $this->nom = $nom;
    }
    /**
     * @return text $nom
     */
    public function getNom()
    {
        return $this->nom;
    }
    /**
     * @param BDepartement $departements
     */
    public function addDepartement(Departement $departement) {
        $departement->setRegion($this);
        // Si l'objet fait déjà partie de la collection on ne l'ajoute pas
        if (!$this->departements->contains($departement)) {
            $this->departements->add($departement);
        }
    }
    /**
     * @return ArrayCollection $departements
     */
    public function getDepartements() {
        return $this->departements;
    }
    public function __construct() {
        $this->departements = new ArrayCollection();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
namespace WaldoRelationBundleEntity;
use DoctrineORMMapping as ORM;
/**
 * @ORMTable(name="Departement")
 * @ORMEntity
 */
class Departement
{
    /**
     * @var decimal $identifiantDepartement
     *
     * @ORMColumn(name="idDepartement", type="bigint", nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy="IDENTITY")
     */
    private $identifiantDepartement;
    /**
     * @var text $nom
     *
     * @ORMColumn(name="nom", type="string", length=60, nullable=true)
     */
    private $nom;
    /**
     * @var Region $region
     *
     * @ORMManyToOne(targetEntity="Region", inversedBy="departements", cascade={"persist", "merge"})
     * @ORMJoinColumns({
     *  @ORMJoinColumn(name="Region_idRegion", referencedColumnName="idRegion")
     * })
     */
    private $region;
    /**
     * @return decimal $identifiantDepartement
     */
    public function getIdentifiantDepartement()
    {
        return $this->identifiantDepartement;
    }
    /**
     * @param text $nom
     */
    public function setNom($nom)
    {
        $this->nom = $nom;
    }
    /**
     * @return text $nom
     */
    public function getNom()
    {
        return $this->nom;
    }
    /**
     * @param BRegion $region
     */
    public function setRegion(Region $region)
    {
        $this->region = $region;
    }
    /**
     * @return BRegion $region
     */
    public function getRegion()
    {
        return $this->region;
    }
}

Avec ce code on pourra faire ce genre de chose :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$coteDOr = new Departement();
$coteDOr->setNom("Côte d'Or");
$ain = new Departement();
$ain->setNom("Ain");
$region = new Region();
$region->setNom("Bourgogne");
$region->addDepartement($coteDOr);
$region->addDepartement($ain);
//ou, mais dans ce cas il faut faire attention à l'ordre de persistance
$coteDOr->setRegion($region);
$ain->setRegion($region);

Explication :

1
2
3
4
5
6
7
/**
* Extrait de la classe Region
* @var Collection $departements
*
* @ORMOneToMany(targetEntity="Departement", mappedBy="region", cascade={"persist", "remove", "merge"})
*/
private $departements;

L’annotation OneToMany définie que la propriété $departements peut contenir un ou plusieurs objets, $departements est de typeArrayCollection.
L’attribut targetEntity détermine de quelle classe dépendent les objets que $departements peut contenir.
L’attribut mappedBy détermine le nom de la propriété présente dans la classe visée (Departement) qui sert de lien.
cascade={"persist", "remove", "merge"}) : permet de définir le comportement lors de la persistance de l’objet Client.

1
2
3
4
5
6
7
8
9
10
/**
* Extrait de la classe Departement
* @var Region $region
*
* @ORMManyToOne(targetEntity="Region", cascade={"persist", "remove", "merge"})
* @ORMJoinColumns({
*  @ORMJoinColumn(name="Region_idRegion", referencedColumnName="idRegion")
* })
*/
private $region;

L’annotation ManyToOne définie que la propriété $region est liée uniquement à un objet de type Region.
L’attribut targetEntity définit la classe visée.
cascade={"persist", "remove", "merge"}) : permet de définir le comportement lors de la persistance de l’objet Client.
L’annotation JoinColumns va permettre de définir quels champs de la table sont utilisés pour lier les deux entités.
L’annotation JoinColumn permet de déterminer quels champs de la base de données permettent la relation.

L’attribut name correspond au champ de la table Departement qui permet la relation.
L’attribut referencedColumnName est le nom du champ de la table visée qui permet la relation.

Attention les valeur de name et referencedColumnName sont les noms des champs qui vont apparaître dans le SQL, alors que l’attributtargetEntity ou mappedBy prend le nom de l’entité (la classe) et non le nom de la table.

Copy from http://mon-beulogue.com/2012/01/24/relation-onetomany-et-manytoone-des-entites-doctrine/

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s