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,

From the book,

  • 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,

many to one relationship

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,

Many to one relationships

Few things to remember in here,

  • Correct Many to one mapping syntax is ‘manyToOne’ NOT ‘ManyToOne’.
  • ‘Home\TestBundle\Entity\Product’ 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, ‘<target_table name>_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,

Many to one inversed by

The code for the Supplier table would be as follows,

One to many relationship

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.


See more on these commands,

I hope you enjoyed my post. Looking forward to see you soon with another article. Cheers!




Leave a Reply

Your email address will not be published. Required fields are marked *