MBO-SD : De site voor software developer in het MBO
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
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
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.