Relaties maken in Symfony

Maken van een relatie - OneToMany

Relaties werken altijd vanuit Entities en het maken doe je in dezelfde functie als het maken of wijzigen van een Entity. In ons voorbeeld hebben wij al een entity Book en een entity Author, maar de relatie onderling (foreignkey in de database en de functies in de entities) is er nog niet. We gaan de relatie maken vanuit de entity Author naar Book (een auteur heeft meerdere boeken, elk boek heeft een auteur). We starten met het commando:
symfony console make:entitiy Author
Je krijgt daarna een hele serie vragen, we tonen eerst alle antwoorden en gaan dan per vraag in op wat er gevraagd wordt.

symfony console make:entity Author
 Your entity already exists! So let's add some new fields!

 New property name (press  to stop adding fields):
 > books

 Field type (enter ? to see all types) [string]:
 > relation

 What class should this entity be related to?:
 > Book

What type of relationship is this?
 ------------ -------------------------------------------------------------------
  Type         Description
 ------------ -------------------------------------------------------------------
  ManyToOne    Each Author relates to (has) one Book.
               Each Book can relate to (can have) many Author objects.

  OneToMany    Each Author can relate to (can have) many Book objects.
               Each Book relates to (has) one Author.

  ManyToMany   Each Author can relate to (can have) many Book objects.
               Each Book can also relate to (can also have) many Author objects.

  OneToOne     Each Author relates to (has) exactly one Book.
               Each Book also relates to (has) exactly one Author.
 ------------ -------------------------------------------------------------------

 Relation type? [ManyToOne, OneToMany, ManyToMany, OneToOne]:
 > OneToMany

 A new property will also be added to the Book class so that you can access and set the related Author object from it.

 New field name inside Book [author]:
 > author

 Is the Book.author property allowed to be null (nullable)? (yes/no) [yes]:
 > no

 Do you want to activate orphanRemoval on your relationship?
 A Book is "orphaned" when it is removed from its related Author.
 e.g. $author->removeBook($book)

 NOTE: If a Book may *change* from one Author to another, answer "no".

 Do you want to automatically delete orphaned App\Entity\Book objects (orphanRemoval)? (yes/no) [no]:
 > no

 updated: src/Entity/Author.php
 updated: src/Entity/Book.php

 Add another property? Enter the property name (or press  to stop adding fields):
 >



  Success!


 Next: When you're ready, create a migration with symfony console make:migration
Vraag 1 - New property - omdat een Auteur meerdere boeken kan hebben in ons voorbeeld is het antwoord op deze vraag books in meervoud, de property geeft immers mogelijke meerdere boeken terug.
New property name (press  to stop adding fields):
> books
Vraag 2 - Field type - is het soort property, in dit geval kies je voor relation, op deze manier krijg je een wizzard die je helpt (later op krijg je alle mogelijke relatie-soorten dan te zien)
Field type (enter ? to see all types) [string]:
> relation
Vraag 3 - What class - We linken naar een Entity dus het antwoord is Book. Let goed op dat je dit altijd met een hoofdletter schrijft. Entities zijn altijd hoofdletters.
What class should this entity be related to?:
> Book
Vraag 4 - What type of - Als je de wizzard gebruikt (relation) bij vraag twee krijg je nu heel handig alle mogelijke relaties en hoe deze in elkaar zou zitten. Lees de relaties goed door en kies dan. In ons geval is het een OneToMany elke Auteur heeft meerdere boeken, elk boek heeft 1 auteur.
What type of relationship is this?
------------ -------------------------------------------------------------------
Type         Description
------------ -------------------------------------------------------------------
ManyToOne    Each Author relates to (has) one Book.
Each Book can relate to (can have) many Author objects.

OneToMany    Each Author can relate to (can have) many Book objects.
Each Book relates to (has) one Author.

ManyToMany   Each Author can relate to (can have) many Book objects.
Each Book can also relate to (can also have) many Author objects.

OneToOne     Each Author relates to (has) exactly one Book.
Each Book also relates to (has) exactly one Author.
------------ -------------------------------------------------------------------

Relation type? [ManyToOne, OneToMany, ManyToMany, OneToOne]:
> OneToMany
Vraag 5 - New field name - De naam die je wilt geven in de Entity. In dit geval author (let op kleine letters). Dit is uiteindelijke je foreign key, let op je hoeft (mag) geen _id mee te geven. Dit doet Symfony zelf. Wat je hier opgeeft is de naam in de Book entity en niet het veld in de database, die regelt Symfony als je de make:migration uitvoert.

A new property will also be added to the Book class so that you can access and set the related Author object from it.

New field name inside Book [author]:
> author
Vraag 6 - Is the Book,author - Deze vraag is door jou zelf te bepalen, als je dit doet als de relaties helemaal nieuw zijn of als er nog geen data in de database staat zal dit in veel gevallen no zijn, hij mag niet null zijn. Maar Als er al data in je database staat kan dit fout gaan bij het maken van de migraties. Denk goed na over deze vraag.
Is the Book.author property allowed to be null (nullable)? (yes/no) [yes]:
> no
Vraag 7 - Do you want to - De orphanRemoval is een gevaarlijke optie, als je als antwoord yes kiest zullen alle boeken gewist worden als je de auteur in je database wist. Dit kan handig zijn, maar vaak zou je juist een foutmelding willen als je per ongeluk een nog gebruikte auteur zou wissen. Ook hier geldt, denk goed na over jouw antwoord en bij twijfel kies no
Do you want to activate orphanRemoval on your relationship?
A Book is "orphaned" when it is removed from its related Author.
e.g. $author->removeBook($book)

NOTE: If a Book may *change* from one Author to another, answer "no".

Do you want to automatically delete orphaned App\Entity\Book objects (orphanRemoval)? (yes/no) [no]:
>

De ManyToOne variant

Als je de relatie zou maken vanuit Book in plaats van Author krijg je alle vragen hetzelfde, maar de relatie zou dan anders zijn, onderstaand de code die je dan zou krijgen.
Belangrijkste verschillen

  • De naam van de property is enkelvoud (het is 1 auteur)
  • Het veld in de Author property is nu meervoud (meerdere boeken per auteur)
  • Je kiest de ManyToOne option
symfony console make:entity Book
 Your entity already exists! So let's add some new fields!

 New property name (press  to stop adding fields):
 > author

 Field type (enter ? to see all types) [string]:
 > relation

 What class should this entity be related to?:
 > Author

What type of relationship is this?
 ------------ -------------------------------------------------------------------
  Type         Description
 ------------ -------------------------------------------------------------------
  ManyToOne    Each Book relates to (has) one Author.
               Each Author can relate to (can have) many Book objects.

  OneToMany    Each Book can relate to (can have) many Author objects.
               Each Author relates to (has) one Book.

  ManyToMany   Each Book can relate to (can have) many Author objects.
               Each Author can also relate to (can also have) many Book objects.

  OneToOne     Each Book relates to (has) exactly one Author.
               Each Author also relates to (has) exactly one Book.
 ------------ -------------------------------------------------------------------

 Relation type? [ManyToOne, OneToMany, ManyToMany, OneToOne]:
 > ManyToOne

 Is the Book.author property allowed to be null (nullable)? (yes/no) [yes]:
 > yes

 Do you want to add a new property to Author so that you can access/update Book objects from it - e.g. $author->getBooks()? (yes/no) [yes]:
 > yes

 A new property will also be added to the Author class so that you can access the related Book objects from it.

 New field name inside Author [books]:
 > books

 updated: src/Entity/Book.php
 updated: src/Entity/Author.php

 Add another property? Enter the property name (or press  to stop adding fields):
 >



  Success!


 Next: When you're ready, create a migration with symfony console make:migration
Voorbeeld van de ManyToOne

De ManyToMany

Bij een ManyToMany relatie hebben beide kanten de mogelijkheid om meerdere te hebben. In het voorbeeld van de boeken zou dit wel eens goed waar kunnen zijn. Sommige boeken hebben maar 1 schrijven, de Harry Potter reeks is bijvoorbeeld geschreven door JK Rowling. Een ManyToOne relatie dus. Maar sommige boeken worden ook door meerdere personen geschreven. Als deze website (MBO-SD) in een boekvorm uitgegeven zou worden dan zou het meerdere auteurs hebben omdat er meerdere mensen mee schrijven. In dat laatste geval is er geen sprake van een ManyToOne of een OneToMany maar een ManyToMany.

ManyToMany kan niet in een standaard database

Een ManyToMany relatie bestaat in een ERD wel, maar in een RDBMS als MySQL, SQLite, Postgres en MariaDB kan deze oplossing niet. Er zal dan altijd een koppeltabel gemaakt moeten worden en zo een ManyToOne en OneToMany relatie meegegeven worden. Zie het onderstaande plaatje wat de uitkomst zou zijn.

Belangrijke ManyToMany informatie

Bij een ManyToMany moet je met een paar dingen rekening houden.

  • Beide properties zijn meervoud
  • De properties zijn zonder _id, dit doet Symfony zelf
  • In de koppeltabel komen ALLEEN de foreign keys naar beide tabellen
  • Zou je toch in de koppeltabel andere data willen stoppen, is het geen ManyToMany meer. Je moet dan een nieuwe Entity maken en met een ManyToOne/ OneToMany relatie de andere Entities aan elkaar koppelen.

Voorbeeld van de ManyToMany

symfony console make:entity Book
 Your entity already exists! So let's add some new fields!

 New property name (press  to stop adding fields):
 > authors

 Field type (enter ? to see all types) [string]:
 > relation

 What class should this entity be related to?:
 > Author

What type of relationship is this?
 ------------ -------------------------------------------------------------------
  Type         Description
 ------------ -------------------------------------------------------------------
  ManyToOne    Each Book relates to (has) one Author.
               Each Author can relate to (can have) many Book objects.

  OneToMany    Each Book can relate to (can have) many Author objects.
               Each Author relates to (has) one Book.

  ManyToMany   Each Book can relate to (can have) many Author objects.
               Each Author can also relate to (can also have) many Book objects.

  OneToOne     Each Book relates to (has) exactly one Author.
               Each Author also relates to (has) exactly one Book.
 ------------ -------------------------------------------------------------------

 Relation type? [ManyToOne, OneToMany, ManyToMany, OneToOne]:
 > ManyToMany

 Do you want to add a new property to Author so that you can access/update Book objects from it - e.g. $author->getBooks()? (yes/no) [yes]:
 > yes

 A new property will also be added to the Author class so that you can access the related Book objects from it.

 New field name inside Author [books]:
 > books

 updated: src/Entity/Book.php
 updated: src/Entity/Author.php

 Add another property? Enter the property name (or press  to stop adding fields):
 >



  Success!


 Next: When you're ready, create a migration with symfony console make:migration
Voorbeeld van het maken van de ManyToMany relatie

OneToOne

Bij een OneToOne relatie koppel je twee tabellen aan elkaar. Dit doe je als je bepaalde data wilt scheiden, maar eigenlijk is het niet nodig. Situaties waar dit soms in gebeurt zijn als de data van een tabel erg groot wordt (heel veel velden/ properties) en dat er voor gekozen wordt om bepaalde data uit elkaar te halen, of als een onderdeel van de tabel dezelfde namen zou bevatten.
Een voorbeeld hiervan is bij een bestelling dat een klant een bezorg- en factuuradres heeft. Beide zijn adressen maar zijn anders, gekoppeld aan dezelfde bestelling. De Order entity heeft dan twee velden met een OneToOne relatie, een delivery_address en invoice_address. Beide velden maak je los van elkaar aan met de OneToOne relation.