На прошлых уроках мы написали первую сущность, поработали с формой, стандартной авторизацией и авторизацией через соц сети. Однако в реальных приложениях все намного сложнее: есть многочисленные связи между сущностями, которые надо правильно обрабатывать. К счастью, Symfony в качестве инструмента с базой данных использует Doctrine, которая очень удобна как раз для решения вопросов отношений. Сегодня мы с вами познакомимся с первым типом отношений — ManyToOne/OnyToMany.
Основы ассоциаций в Doctrine
Мы уже делали сущность Post на одном из первых уроков, поэтому мы не будем ничего переписывать, а прямо в ней сделаем отношение с другой сущностью, Comment. Для начала давайте создадим ее.
Давайте сначала поразмышляем, как правильно определить отношение между сущностями. У нас есть комментарии и есть публикация. У публикации может быть много комментариев, но комментарий может принадлежать только одной сущности. Отсюда и возникает, что мы должны определить к таблице Post и User отношение ManyToOne, потому как только одному посту и одному пользователю могут принадлежать много комментариев, но не наоборот.
Аннотация ManyToOne принимает несколько аргументов, один из них — targetEntity — является ссылкой (можно указывать как Entity::class, так и полный неймспейс до сущности) на класс для связи, другой inversedBy, где указывается поле для связи. В нашем случае к сущностям User и Post мы позже добавим поле comments. Важно заметить, что связь с двух сторон можно не указывать, потому как доктрина умная и додумает сама, как соединить (а именно по id), но если вам понадобится получить комментарии для всех постов, то удобно достать их через публикацию, хоть это и не очень быстро.
Кстати, @JoinColumn() можно не указывать, доктрина все равно создаст нам такие же поля, как и с ней, однако если вы хотите изменить название поля или референс, то надо использовать данную аннотацию.
Теперь давайте укажем связи в сущностях Post и User, делается это следующим образом:
При этом в конструкторе классов Post и User надо определить поле comments как коллекцию объектов:
Вы могли заметить небольшие отличия в аннотациях ManyToOne и OneToMany, а именно на то, что у них разные атрибуты — inversedBy и mappedBy. inversedBy указывается в аннотации ManyToOne и указывает на родителя связи, mappedBy же указывают на обратную сторону двунаправленной связи.
При этом не надо указывать @ORMColumn() для полей связи, так как тип связующего поля возьмется по id, и если вы укажете, то аннотация @ManyToOne или @OneToMany просто не выполнится. Теперь можете запускать миграции:
Если вы посмотрите в базу, то увидите таблицу comment со следующими полями:
Все сработало ровно так, как нам и нужно было.
Добавление комментария
Для добавления комментария к посту мы будем работать с коллекциями. Для этого нам сначала нужно добавить следующие методы в сущность Post:
У ArrayCollection достаточно простой API, советую познакомиться с ним по ссылке.
В первом методе мы сеттим Post и проверяем, содержится ли уже в коллекции комментарий с таким id, если нет, добавляем, если да, ничего не делаем. Ну и удаление работает так же просто: вызываем метод коллекции removeElement, куда передаем сущность Comment. Теперь давайте создадим форму:
Кажется, все готово, чтобы можно было под постом добавить комментарий. Для этого сначала напишем экшен контроллера PostsController, а потом отрендерим шаблон:
Как вы могли заметить, мы по одному роуту и показываем публикацию, и создаем комментарий. Примерно так может выглядеть итоговый шаблон:
И вот теперь нам понадобилась связь в сущности Post, так как через post.comments мы достали все комментарии, принадлежащие конкретному посту. Так же вы можете достать все комментария юзера через user.comments в шаблоне или $this->getUser()->getComments() в коде.
Итого
На этом пока все. Еще больше концепций и правил по работе с отношениями мы рассмотрим в следующих уроках.
Если у вас будут проблемы с последней версией Symfony или с пониманием работы отношений, пишите вопросы в комментариях.
Association Mapping
This chapter explains mapping associations between objects.
Instead of working with foreign keys in your code, you will always work with references to objects instead and Doctrine will convert those references to foreign keys internally.
- A reference to a single object is represented by a foreign key.
- A collection of objects is represented by many foreign keys pointing to the object holding the collection
This chapter is split into three different sections.
- A list of all the possible association mapping use-cases is given.
- Association Mapping are explained that simplify the use-case examples.
- Association Mapping are introduced that contain entities in associations.
One tip for working with relations is to read the relation from left to right, where the left word refers to the current Entity. For example:
- OneToMany — One instance of the current Entity has Many instances (references) to the refered Entity.
- ManyToOne — Many instances of the current Entity refer to One instance of the refered Entity.
- OneToOne — One instance of the current Entity refers to One instance of the refered Entity.
See below for all the possible relations.
An association is considered to be unidirectional if only one side of the association has
a property referring to the other side.
To gain a full understanding of associations you should also read about owning and inverse sides of associations
Many-To-One, Unidirectional
A many-to-one association is the most common association between objects. Example: Many Users have One Address:
- PHP
The above @JoinColumn is optional as it would default to address_id and id anyways. You can omit it and let it use the defaults.
Generated MySQL Schema:
One-To-One, Unidirectional
Here is an example of a one-to-one association with a Product entity that references one Shipment entity.
- PHP
Note that the @JoinColumn is not really necessary in this example, as the defaults would be the same.
Generated MySQL Schema:
One-To-One, Bidirectional
Here is a one-to-one relationship between a Customer and a Cart . The Cart has a reference back to the Customer so it is bidirectional.
Here we see the mappedBy and inversedBy annotations for the first time. They are used to tell Doctrine which property on the other side refers to the object.
- PHP
Note that the @JoinColumn is not really necessary in this example, as the defaults would be the same.
Generated MySQL Schema:
We had a choice of sides on which to place the inversedBy attribute. Because it is on the Cart , that is the owning side of the relation, and thus holds the foreign key.
One-To-One, Self-referencing
You can define a self-referencing one-to-one relationships like below.
Note that the @JoinColumn is not really necessary in this example, as the defaults would be the same.
With the generated MySQL Schema:
One-To-Many, Bidirectional
A one-to-many association has to be bidirectional, unless you are using a join table. This is because the many side in a one-to-many association holds the foreign key, making it the owning side. Doctrine needs the many side defined in order to understand the association.
This bidirectional mapping requires the mappedBy attribute on the one side and the inversedBy attribute on the many side.
This means there is no difference between a bidirectional one-to-many and a bidirectional many-to-one.
- PHP
Note that the @JoinColumn is not really necessary in this example, as the defaults would be the same.
Generated MySQL Schema:
One-To-Many, Unidirectional with Join Table
A unidirectional one-to-many association can be mapped through a join table. From Doctrine’s point of view, it is simply mapped as a unidirectional many-to-many whereby a unique constraint on one of the join columns enforces the one-to-many cardinality.
The following example sets up such a unidirectional one-to-many association:
- PHP
Generates the following MySQL Schema:
One-To-Many, Self-referencing
You can also setup a one-to-many association that is self-referencing. In this example we setup a hierarchy of Category objects by creating a self referencing relationship. This effectively models a hierarchy of categories and from the database perspective is known as an adjacency list approach.
- PHP
Note that the @JoinColumn is not really necessary in this example, as the defaults would be the same.
Generated MySQL Schema:
Many-To-Many, Unidirectional
Real many-to-many associations are less common. The following example shows a unidirectional association between User and Group entities:
- PHP
Generated MySQL Schema:
Why are many-to-many associations less common? Because frequently you want to associate additional attributes with an association, in which case you introduce an association class. Consequently, the direct many-to-many association disappears and is replaced by one-to-many/many-to-one associations between the 3 participating classes.
Many-To-Many, Bidirectional
Here is a similar many-to-many relationship as above except this one is bidirectional.
- PHP
The MySQL schema is exactly the same as for the Many-To-Many uni-directional case above.
Owning and Inverse Side on a ManyToMany Association
For Many-To-Many associations you can chose which entity is the owning and which the inverse side. There is a very simple semantic rule to decide which side is more suitable to be the owning side from a developers perspective. You only have to ask yourself which entity is responsible for the connection management, and pick that as the owning side.
Take an example of two entities Article and Tag . Whenever you want to connect an Article to a Tag and vice-versa, it is mostly the Article that is responsible for this relation. Whenever you add a new article, you want to connect it with existing or new tags. Your Create Article form will probably support this notion and allow specifying the tags directly. This is why you should pick the Article as owning side, as it makes the code more understandable:
This allows to group the tag adding on the Article side of the association:
Many-To-Many, Self-referencing
You can even have a self-referencing many-to-many association. A common scenario is where a User has friends and the target entity of that relationship is a User so it is self referencing. In this example it is bidirectional so User has a field named $friendsWithMe and $myFriends .
Generated MySQL Schema:
Mapping Defaults
The @JoinColumn and @JoinTable definitions are usually optional and have sensible default values. The defaults for a join column in a one-to-one/many-to-one association is as follows:
As an example, consider this mapping:
- PHP
This is essentially the same as the following, more verbose, mapping:
- PHP
The @JoinTable definition used for many-to-many mappings has similar defaults. As an example, consider this mapping:
- PHP
This is essentially the same as the following, more verbose, mapping:
- PHP
In that case, the name of the join table defaults to a combination of the simple, unqualified class names of the participating classes, separated by an underscore character. The names of the join columns default to the simple, unqualified class name of the targeted class followed by _id. The referencedColumnName always defaults to id, just as in one-to-one or many-to-one mappings.
If you accept these defaults, you can reduce the mapping code to a minimum.
Collections
Unfortunately, PHP arrays, while being great for many things, are missing features that make them suitable for lazy loading in the context of an ORM. This is why in all the examples of many-valued associations in this manual we will make use of a Collection interface and its default implementation ArrayCollection that are both defined in the DoctrineCommonCollections namespace. A collection implements the PHP interfaces ArrayAccess , Traversable and Countable .
The Collection interface and ArrayCollection class, like everything else in the Doctrine namespace, are neither part of the ORM, nor the DBAL, it is a plain PHP class that has no outside dependencies apart from dependencies on PHP itself (and the SPL). Therefore using this class in your model and elsewhere does not introduce a coupling to the ORM.
Initializing Collections
You should always initialize the collections of your @OneToMany and @ManyToMany associations in the constructor of your entities:
The following code will then work even if the Entity hasn’t been associated with an EntityManager yet:
5. Association Mapping¶
This chapter explains mapping associations between objects.
Instead of working with foreign keys in your code, you will always work with references to objects instead and Doctrine will convert those references to foreign keys internally.
- A reference to a single object is represented by a foreign key.
- A collection of objects is represented by many foreign keys pointing to the object holding the collection
This chapter is split into three different sections.
- A list of all the possible association mapping use-cases is given.
- Mapping Defaults are explained that simplify the use-case examples.
- Collections are introduced that contain entities in associations.
To gain a full understanding of associations you should also read about owning and inverse sides of associations
5.1. Many-To-One, Unidirectional¶
A many-to-one association is the most common association between objects.
- PHP
The above @JoinColumn is optional as it would default to address_id and id anyways. You can omit it and let it use the defaults.
Generated MySQL Schema:
5.2. One-To-One, Unidirectional¶
Here is an example of a one-to-one association with a Product entity that references one Shipping entity. The Shipping does not reference back to the Product so that the reference is said to be unidirectional, in one direction only.
- PHP
Note that the @JoinColumn is not really necessary in this example, as the defaults would be the same.
Generated MySQL Schema:
5.3. One-To-One, Bidirectional¶
Here is a one-to-one relationship between a Customer and a Cart . The Cart has a reference back to the Customer so it is bidirectional.
- PHP
Note that the @JoinColumn is not really necessary in this example, as the defaults would be the same.
Generated MySQL Schema:
See how the foreign key is defined on the owning side of the relation, the table Cart .
5.4. One-To-One, Self-referencing¶
You can define a self-referencing one-to-one relationships like below.
Note that the @JoinColumn is not really necessary in this example, as the defaults would be the same.
With the generated MySQL Schema:
5.5. One-To-Many, Bidirectional¶
A one-to-many association has to be bidirectional, unless you are using an additional join-table. This is necessary, because of the foreign key in a one-to-many association being defined on the “many” side. Doctrine needs a many-to-one association that defines the mapping of this foreign key.
This bidirectional mapping requires the mappedBy attribute on the OneToMany association and the inversedBy attribute on the ManyToOne association.
- PHP
Note that the @JoinColumn is not really necessary in this example, as the defaults would be the same.
Generated MySQL Schema:
5.6. One-To-Many, Unidirectional with Join Table¶
A unidirectional one-to-many association can be mapped through a join table. From Doctrine’s point of view, it is simply mapped as a unidirectional many-to-many whereby a unique constraint on one of the join columns enforces the one-to-many cardinality.
The following example sets up such a unidirectional one-to-many association:
- PHP
Generates the following MySQL Schema:
5.7. One-To-Many, Self-referencing¶
You can also setup a one-to-many association that is self-referencing. In this example we setup a hierarchy of Category objects by creating a self referencing relationship. This effectively models a hierarchy of categories and from the database perspective is known as an adjacency list approach.
- PHP
Note that the @JoinColumn is not really necessary in this example, as the defaults would be the same.
Generated MySQL Schema:
5.8. Many-To-Many, Unidirectional¶
Real many-to-many associations are less common. The following example shows a unidirectional association between User and Group entities:
- PHP
Generated MySQL Schema:
Why are many-to-many associations less common? Because frequently you want to associate additional attributes with an association, in which case you introduce an association class. Consequently, the direct many-to-many association disappears and is replaced by one-to-many/many-to-one associations between the 3 participating classes.
5.9. Many-To-Many, Bidirectional¶
Here is a similar many-to-many relationship as above except this one is bidirectional.
- PHP
The MySQL schema is exactly the same as for the Many-To-Many uni-directional case above.
5.9.1. Owning and Inverse Side on a ManyToMany association¶
For Many-To-Many associations you can chose which entity is the owning and which the inverse side. There is a very simple semantic rule to decide which side is more suitable to be the owning side from a developers perspective. You only have to ask yourself, which entity is responsible for the connection management and pick that as the owning side.
Take an example of two entities Article and Tag . Whenever you want to connect an Article to a Tag and vice-versa, it is mostly the Article that is responsible for this relation. Whenever you add a new article, you want to connect it with existing or new tags. Your create Article form will probably support this notion and allow to specify the tags directly. This is why you should pick the Article as owning side, as it makes the code more understandable:
This allows to group the tag adding on the Article side of the association:
5.10. Many-To-Many, Self-referencing¶
You can even have a self-referencing many-to-many association. A common scenario is where a User has friends and the target entity of that relationship is a User so it is self referencing. In this example it is bidirectional so User has a field named $friendsWithMe and $myFriends .
Generated MySQL Schema:
5.11. Mapping Defaults¶
The @JoinColumn and @JoinTable definitions are usually optional and have sensible default values. The defaults for a join column in a one-to-one/many-to-one association is as follows:
As an example, consider this mapping:
- PHP
This is essentially the same as the following, more verbose, mapping:
- PHP
The @JoinTable definition used for many-to-many mappings has similar defaults. As an example, consider this mapping:
- PHP
This is essentially the same as the following, more verbose, mapping:
- PHP
In that case, the name of the join table defaults to a combination of the simple, unqualified class names of the participating classes, separated by an underscore character. The names of the join columns default to the simple, unqualified class name of the targeted class followed by “_id”. The referencedColumnName always defaults to “id”, just as in one-to-one or many-to-one mappings.
If you accept these defaults, you can reduce the mapping code to a minimum.
5.12. Collections¶
Unfortunately, PHP arrays, while being great for many things, are missing features that make them suitable for lazy loading in the context of an ORM. This is why in all the examples of many-valued associations in this manual we will make use of a Collection interface and its default implementation ArrayCollection that are both defined in the DoctrineCommonCollections namespace. A collection implements the PHP interfaces ArrayAccess , Traversable and Countable .
The Collection interface and ArrayCollection class, like everything else in the Doctrine namespace, are neither part of the ORM, nor the DBAL, it is a plain PHP class that has no outside dependencies apart from dependencies on PHP itself (and the SPL). Therefore using this class in your model and elsewhere does not introduce a coupling to the ORM.
5.13. Initializing Collections¶
You should always initialize the collections of your @OneToMany and @ManyToMany associations in the constructor of your entities:
The following code will then work even if the Entity hasn’t been associated with an EntityManager yet:
Doctrine 2: Correct way to use a Many-To-Many association
When working in Symfony and using Doctrine 2 ORM you sometimes need to use a many-to-many association between entities. This relationship means that a blog post can have multiple categories. And categories can be used in multiple blog posts.
As you can see we need a junction table for this. This junction tables links the blog posts with the correct categories. So how is the simplest and most correct way to do this in Doctrine 2 with entities?
Creating Entities
To get started we first create our BlogPost entity as seen below:
So here we defined $categories as many-to-many association with targetEntity equal to Category. Our $categories variable will be holding a collection of Category. To be able to work with collections we first need to instantiate it in our constructor. This allows us to add or remove categories to a blog post. If we don’t instantiate this ArrayCollection on construction, then you will get errors.
On our Category entity we apply the same rules. This similar to our BlogPost entity.
Getters and Setters
So now that we defined our properties for our entities. And also made sure we have a collection when the entities get constructed. We can now implement our getter and setter methods for $categories and $blogPosts.
Getting a collection
So first we are going to create some basic get methods:
Both get methods returns DoctrineCommonCollectionsCollection. Not ArrayCollection like we created in our constructors. If you try to return ArrayCollection then you will get the following error:
Type error: Return value of AppEntityBlogPost::getCategories() must be an instance of DoctrineCommonCollectionsArrayCollection, instance of DoctrineORMPersistentCollection returned
So why is this? Well if we look deeper in the Doctrine classes we can find the following:
- ArrayCollection is a class that implements the interface Collection:
class ArrayCollection implements Collection, Selectable - PersistentCollection is class that extends AbstractLazyCollection:
final class PersistentCollection extends AbstractLazyCollection implements Selectable - but AbstractLazyCollection implements Collection:
abstract class AbstractLazyCollection implements Collection
Collection is an interface and we should use that instead. Use your interfaces and not your implementations! Now it does not matter if the actual result is an ArrayCollection or a PersistentCollection. They are all implementations of the interface. In our entities we work with an array collection but Doctrine uses a persistent collection to lazy load our properties only when required. This is a mechanic of doctrine to improve performance and memory usage.
Adding to a collection
Instead of using a set method, we are going to create methods for adding and removing categories or blog posts to our collections.
As you can see we first check if the entity we add to the collection is already part of that collection. If not we add this to our collection. We also need to make sure that both entities are linked together and have each other in both collections. Its important that both entities always have the correct data at any time.
Removing from a collection
So if we have a method to add objects to a collection, then we should also have one to remove them.
So this is similar to adding to a collection. The difference is that we first check if the object does exist in the collection before removing it. We can’t remove something that does not exist. Then we also make sure that this change is applied to both entities.
Beware of many-to-many
In some cases you don’t need a many-to-many association. When you want other data in your junction table, the link between both entities. Then you should use a one-to-many/many-to-one relationship. You should create a third entity that is the link between both entities. This way you can add multiple columns to the join table. Your join table is an entity. It is part of your business logic if it does more then linking 2 entities together.
You should think this trough before creating a many-to-many relationship. Here an example of a many-to-many that was changed to a one-to-many/many-to-one because we needed to also know when the user started working on the company and for which salary.
Conclusion
Today we learned one correct way to create a many-to-many association. There are more solutions to this problem. Anyone that has other solutions are free to discuss them here. And we also learned a bit about collections. How they work in the background of Doctrine. We should also be carefull to to abuse many-to-many associations and maybe think about it. Maybe we should use a one-to-many/many-to-one association?As always think before you code!
Jeffrey Verreckt is a professional Web Developer skilled in PHP and JavaScript focused on mastering best practices, patterns and architectures for web development.
Technology, Life Lessons and so much more.
Articles by Anjana Silva
M | T | W | T | F | S | S |
---|---|---|---|---|---|---|
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 |
Archives
- February 2019
- August 2018
- April 2018
- March 2018
- May 2016
- February 2016
- January 2016
- December 2015
- October 2015
- August 2015
- July 2015
- February 2015
- January 2015
- July 2014
- June 2014
- May 2014
- April 2014
- March 2014
- January 2014
- November 2013
- April 2013
Symfony 2 News
- Launch of the official Symfony store
- Symfony 5.1.2 released
- A Week of Symfony #702 (8-14 June 2020)
- Symfony 5.1.1 released
- Symfony 5.0.10 released
CakePHP Articles
- Working From Home — A Developer’s View
- CakePHP Virtual Meetup
- PHP Quality Assurance Tools with CakePHP
- Working with CakePHP Authorization
- Benefits of S.E.O
Many-to-one relationship mapping using Doctrine 2 in Symfony 2 in YAML
Hello doctrine lovers,
Well come back. In my previous post, we discussed how to map one-to-one relationships. If you have not read it but want to make yourself aware of one-to-one relationship mapping in Doctrine using YAML, make sure you read it before reading this post. So, today I am going to show you how to map many-to-one relationships in both unidirectional and bidirectional ways using Doctrine 2. As you are aware by now I will be using YAML instead of PHP annotations or XML. It is simply because YAML is very easy to understand (though you need to stick with proper indentation, which is not a big deal), will not run into unexpected problems, such as pre-compilers/caching engines tend to ignore comments, which will be used in annotations and few other things. By the way, in Symfony 2, you can use either YAML, Annotations or XML as part of the Doctrine configuration, but use one, not all. Symfony 2 evaluates all these methods equally. At the end of this post, you will learn a technique to evaluate your mapping whether it’s correct or not. So make sure you don’t miss anything in this post.
So back to the topic. Let’s have a quick look at what’s many-to-one relationship is all about. In simple terms, many-to-one is many rows of a table can be relate with only one row of another table. Take a look at the image below,
So basically, what this tells is, one supplier can have more than one product. For an in instance supplier ‘acer’ can have more than one products such as aspire e1 series laptops, e2 series laptops and so on.
Unidirectional – Many to One
In Unidirectional many-to-one mapping, you will only point to the target table from the parent table (same as in the one-to-one example in my previous post). I call ‘product‘ table as the owning side (parent table) and ‘supplier‘ table as the target table. The reason why I declare parent table to be the owning side is below,
- A unidirectional relationship only has an owning side.
- The owning side of a relationship determines the updates to the relationship in the database.
- About owning side : There are 2 references on each side of the association and these 2 references both represent the same association but can change independently of one another. Of course, in a correct application the semantics of the bidirectional association are properly maintained by the application developer (that’s his responsibility). Doctrine needs to know which of these two in-memory references is the one that should be persisted and which not. This is what the owning/inverse concept is mainly used for. “Owning side” and “inverse side” are technical concepts of the ORM technology, not concepts of your domain model. What you consider as the owning side in your domain model can be different from what the owning side is for Doctrine. These are unrelated.
Hence unidirectional relationship only has an owning side, I will be declaring the relevant relationship type which in the ‘Product’ table, which is below,
Since it’s unidirectional, we don’t declare any relationships in the Supplier table, which is the inverse side. However take a look at the code,
Few things to remember in here,
- Correct Many to one mapping syntax is ‘manyToOne’ NOT ‘ManyToOne’.
- ‘HomeTestBundleEntityProduct’ is the location where you need ‘Entities’ to be generated. (discussed below)
- targetEntity is the name of the target table’s Entity (including the directory path if not in the same directory), NOT the table name.
- joinColumn bit can be ignored if you followed standards. Because in Doctrine 2, as a standard it expects, the name of the field (column) in the parent table which is being referred to a target table is in this format, ‘ _id’, so in our example it’s ‘supplier_id’. So if you follow these standards, life will be much easier. However I put this for your additional information.
- referencedColumnName is the field of the target (supplier) table, which is usually the primary key.
Bidirectional – Many to One
This is where you need to declare relationships for both owning (Product) and inverse side (Supplier) tables. The relationship for the owning table which we have declared above will be remain intact, but you need specify the ‘inversedBy‘ (see the image below) and the entity name. ‘inversedBy‘ is the term Doctrine use to reference from owning side of the relationship to the inverse side. Remember, when mapping a bidirectional relationship, inverse side of ‘manyToOne’ is ‘oneToMany’. Let’s see in another perspective. If from product to supplier is ‘manyToOne’ , from supplier to product is ‘oneToMany’. I hope now that’s clear.
The code for the Product table would be as follows,
The code for the Supplier table would be as follows,
I hope you can see the declaration of ‘oneToMany’ section in the above image. Nothing new in here, but few things to remember,
- Correct One to many mapping syntax is ‘oneToMany’ NOT ‘OneToMany’.
- mappedBy is the term used when referencing from inverse side to the owning side.
- targetEntity is the name of the target table’s Entity (including the directory path if not in the same directory), NOT the table name.
- joinColumn bit can be ignored if you followed standards.
So this is all about many to one relationship mapping in Doctrine 2 using YAML in Symfony. One more thing, to correctly check whether your mapping is valid, you can always run these commands in the command prompt and see the results.
- ‘php app/console doctrine:generate:entities HomeTestBundle –no-backup‘ – this command is for generate entities and it will generate entities for you. But if there’s something wrong with the mapping file, this will warn you.
- ‘php app/console doctrine:schema:validate‘ – This command will validate your ORM files against the database. However before run this, you have to run the schema update command at least once, which is ‘php app/console doctrine:schema:update –force‘. If you got problems with ORM files, these commands will fail and warn you with details, so you can debug later.
I hope you enjoyed my post. Looking forward to see you soon with another article. Cheers!