Relations Doctrine dans Symfony : ManyToOne et OneToMany
Une relation Doctrine relie deux entités Symfony : ManyToOne côté propriétaire, qui porte la clé étrangère, OneToMany côté inverse, pour naviguer.
// Plat : le côté propriétaire, qui porte categorie_id. #[ORM\ManyToOne(inversedBy: 'plats')] #[ORM\JoinColumn(nullable: false)] private ?Categorie $categorie = null; // Categorie : le côté inverse. /** @var Collection<int, Plat> */ #[ORM\OneToMany(targetEntity: Plat::class, mappedBy: 'categorie')] #[ORM\OrderBy(['prix' => 'ASC'])] private Collection $plats;
Seul le côté propriétaire compte pour la base : Doctrine lit $plat->getCategorie() pour écrire categorie_id. Le côté inverse, déclaré avec mappedBy, existe pour parcourir categorie.plats dans un template, triés par #[ORM\OrderBy]. inversedBy et mappedBy se répondent par le nom de la propriété d'en face, et JoinColumn(nullable: false) rend la relation obligatoire. Le piège : ajouter un objet à la seule collection inverse. Rien n'est enregistré, puisque Doctrine ne regarde pas ce côté ; c'est pourquoi addPlat() appelle aussi setCategorie(). Un inversedBy qui désigne une propriété inexistante ne casse pas forcément la page, mais doctrine:schema:validate le signale.
Les exercices font mapper la catégorie et la relier aux plats pour ranger la carte de la taverne par catégorie, du moins cher au plus cher, puis afficher sous chaque fiche les avis du livre d'or, chaque nouvel avis étant créé déjà rattaché à son plat avant de remplir le formulaire.
2 exercices font travailler cette notion, en écrivant du code dans le navigateur.
Dans les parcours
- Chaque plat à sa place Symfony pour les devs PHP · chapitre 2 : La cave et le garde-manger
- Le livre d'or Symfony pour les devs PHP · chapitre 3 : Les parchemins de la taverne