The King of Relations: ManyToOne

Selecting between ManyToOne and ManyToMany

Each genus will have many genus_notes. But, each genus_note that someone adds will relate to only one genus. There are only two possible types of relationships, and this is by far the most common. It's called a ManyToOne association.

The second type is called a ManyToMany association. To use a different example, this would be if each product had many tags, but also each tag related to many products.

And when it comes to Doctrine relations - don't trust the Internet! Some people will try to confuse you with other relationships like OneToMany, OneToOne and some garbage about unidirectional and bidirectional associations. Gross. Ignore it all. I guarantee, all of that will make sense really soon.

So your first job is simple: decide if you have a ManyToOne or ManyToMany relationship. And it's easy. Just answer this question:

Do either of the sides of the relationship belong to only one of the other?

Each genus_note belongs to only one genus, so we have a classic ManyToOne relationship.

Setting up a ManyToOne Relation

Forget about Doctrine: just think about the database. If every genus_note should belong to exactly one genus, How would you set that up? You'd probably add a genus_id column to the genus_note table. Simple!

Since we need to add a new column to GenusNote, open that entity class. You probably feel like you want to add a $genusId integer property here. That makes sense. But don't! Instead, add a $genus property and give it a ManyToOne annotation. Inside that, add targetEntity="Genus":

100 lines src/AppBundle/Entity/GenusNote.php
... lines 1 - 10
class GenusNote
... lines 13 - 39
* @ORM\ManyToOne(targetEntity="Genus")
private $genus;
... lines 44 - 98


You can also use the full namespace: AppBundle\Entity\Genus - and that's required if the two entities do not live in the same namespace/directory.

Umm, guys? That's it. Relationship finished. Seriously.

Leave a comment!

  • 2018-02-13 weaverryan

    Hi Mehdi Marchouk!

    Oh boy - it's very complex. I'm really not sure what to recommend :/. Your data structure is *quite* denormalized, and so things are becoming very complex - relational databases just don't do this kind of thing well. You could try to leverage the `json` field type in Doctrine, which would allow you to store whatever data you want inside 1 field. If you do that, make sure you set the server_version config to 5.7 ( so that Doctrine uses the native JSON feature.

    I'm sorry I can't recommend more - this is really a complex, custom situation. My best advice is to try to keep it as simple as possible!


  • 2018-02-13 Mehdi Marchouk

    Thank you for this great reply as usual !
    I think if have a lot of subcategories, I will come up with a lot of tables.
    Those are others explanations :
    This the whole structure :
    - Category can be 1=> an Object or 2=> an Animal (Dog, Cat, Other ....).
    - All animals have the same fields for simplicity.
    - Object can be 1.1.Clothes (T-shirt, Pants, Other ...) or 1.2.Jewelry (Ring, Bracelet, Other ....).
    - For objects, since I can have a lot of tables, I will use an easy solution: Omit the specific fields for subcategories and use just the common fields for all objects.
    - Object's fields are different from Animal's.
    This is an example of using that structure :
    - If I choose Animal , a form appears (choosing which animal and filling Animal fields)
    - If I choose Object or if after I select Jewelry , a form appears (choosing which Jewelry and filling Object fields ).
    So there are 3 levels for Object category ?? The implementation also will be changed because fields are in the parent category ?
    I am sorry but I am blocked on this part.
    Thank you !

  • 2018-02-12 weaverryan

    Hey Mehdi Marchouk!

    Ah yes. This is not an easy problem so solve: in general, the data structure needed for ECommerce & categories is complex! That's part of the reason why something like Sylius exists: ECommerce built on top of Symfony. It may or may not be a good idea for you (it has a lot of features, which can be good or bad depending on your situation!).

    The Tree implementation is probably not needed, because you only have *2* levels of categories (unless I'm wrong). I mean, you have Category -> SubCategory.... NOT Category -> SubCategory -> SubSubCategory....

    Here's what I would do:

    1) Create a Category entity
    2) Create a SubCategory entity. Give this only the fields that are on all sub categories. So, material & type.
    3) Create a ManyToOne relationship from SubCategory to Category
    4) Use Doctrine's inheritance system (http://docs.doctrine-projec... to create a new entity for each *type* of SubCategory. For example, create RingSubCategory and make it extend SubCategory. Give this the "sex" field. Do the same thing for BraceletSubCategory: give it the field color. For the inheritance type, usually the "joined table" is the best idea.

    This setup will allow you to have a Category that relates to many SubCategory's of different *types*. I think it's what you need :).


  • 2018-02-09 Mehdi Marchouk

    I have categories and sub categories with different fields for last sub category child. For example Jewelry category have 2 sub categories , a sub category Ring have these fields : material, type, color. a sub category Bracelet have
    these fields: material, type and sex. I want to design this in doctrine. I did a search and I found this bundle StofDoctrineExtensionsBundle
    using the Tree Doctrine Extension but Ii don't know how to handle those different fields since this Doctrine Extension work with the same
    fields for all categories and sub categories ?
    Can you help me? Thank you!

  • 2017-05-04 Victor Bocharsky

    Hey maxii123 ,

    In this screencast Ryan wants to say that OneToOne relation is actually ManyToOne, i.e. technically it is, they have the same schema in the database. You can see it in examples of Doctrine docs: http://docs.doctrine-projec... . So just Doctrine helps you to control OneToOne relationship which is technically the same as ManyToOne in DB. Does it makes sense for you?


  • 2017-05-03 maxii123

    I'm not sure the apparent dismissal of onetoone in this video is a good thing. It has certainly caused a few issues on a #irc help channel. Lets say I have an address table with a pointer to a country table. many addresses can point to the same country record. surely this is a one to one? OK I admit it. I'm confused.

  • 2016-11-30 Hakim Ch

    Thank you Victor !

  • 2016-11-30 Victor Bocharsky

    Hey Hakim,

    Yes, there's a Database normalization which has several normal forms. It's the first step on the way of database performance optimization.


  • 2016-11-29 Hakim Ch

    You got a point about combining the tables!!! and thank for the extra :D
    Another question, there is a track about tables creation strategy to avoid performance issues ?

  • 2016-11-29 weaverryan

    Hey Hakim Ch!

    Yea, using OneToOne is fine :). I usually avoid it, because technically, you could just combine your Client and ClientInfo tables into one table. By separating them, you're causing yourself more complexity, because now you need to make sure you create a Client and ClientInfo object, and set the Client on the ClientInfo. This can be done well, but it's just easier to have one table (I realize having one big table can have performance drawbacks, so this is a tradeoff of complexity versus performance).

    Also, on a more philosophical level, a OneToOne is nothing more than a ManyToOne, where Doctrine creates a unique index on your foreign key (client_id) to prevent you from having more than one. That's not relevant to your question - just a fun thing to think about (and heck, even ManyToMany is just two ManyToOne relationships automated for you - we talk about that in the new screencast).

    Thanks for the question!

  • 2016-11-29 Hakim Ch

    Hi Ryan,

    I have 2 tables Client, ClientInfo (wich referenced by client_id). the OneToOne relation, so how i can manage that if it not good to use the OneToOne relation ?

  • 2016-10-08 weaverryan

    Hi Yang!

    This is as good a spot as any :). A few things:

    1) It's subjective, but I'm not a huge fan of these "look-up" tables: tables that exist in your database, aren't really ever going to be dynamically updated, and just contain a very few, specific records. I actually like the setup you have in this situation: a normal string column. I use constants in my Post entity class for each valid "source" to keep a nice list of what is a valid source.

    2) But, let's assume that you *do* want to do this: it's still totally valid. And you *can* train the Doctrine Migrations to do this, it's just not automatic. Here's how I do this:

    A) Add the new entity and relationship (but don't remove the old source field yet). Generate a migration. This will contain *just* the code to add the new relationship/column.

    B) Next, we want to migrate the old data into the new location. There are 2 ways to do this, depending on whether or not you're smart enough (I often am not) to write a query that will move the data for you. If you can, you'll simply manually update the migration file generated in step (A), add a new $this->addSql(), and write your new manual query there. This would need to insert the new source records and then update the foreign key column. That's a pretty tricky query (inserting and updating all at once). I don't think that you can insert with one addSql() line, then query for and reference those new columns in a second addSql(), because it's all done in a transaction and so the new records aren't available yet. That's what makes it tricky.

    So if you can't write a big query to do this, then you have, actually, two more options :p. The one I typically do is to create a temporary, custom console command. Then, I will deploy, run the migration from step (A), then run this custom console command, which moves the data. Then on a future deploy, I'll generate and run the migration from step (C). The advantage here is that you have access to the container, entity manager, etc. A different, but similar approach is to get access to and use the container directly inside the migration itself ( I often do a console command instead, because it's much easier to handle things if this data migration fails, which is quite possible if you have a big data set (i.e. you could run out of memory). That's why I add a custom console command, and often make my code smart enough to continue where I left-off, in case the command failed in the middle.


    C) Finally, you'll remove the source column and generate a new migration. Depending on which strategy you use for part (B), you'll either do this at the same time as the other changes, or you'll need to do this in the future, after you deploy and migrate the data, so that the field is still there while you transfer the data.

    So, great question! This isn't something that comes up *all* that often, but it does happen (maybe a few times a year for the KnpU site). I try to write the query if I can, but if I need a little more logic and access to the container, I prefer a console command.


  • 2016-10-07 Yang Liu

    Hi Ryan,

    I can't find the exact tutorial part for my question, so I try to post in here. For example, I have my Entity Post, in which there is the column "source", which would be facebook, twitter, whatever.... In the current state, its just a simple string. easy...
    But when I think of the future, there might be other new sources coming and it would be better when I create a new Entity, for example, Source, with an id and a name. and the id column will get the OneToMany-Relation to the source column in the Post-Entity. (I can recall somewhere in your symfony tutorial, you change the column "subfamily" of the genus and used a new Entity SubFamily instead, did you just recreate both Entities?).
    Thing is, since my Post-table is pretty big now, I can't just recreate both tables. And manually, I would first create a new source table, then add a new column source_id in Post-tabel, find out which id the sources has and update the source_id column, then remove the old source column. This will really suck when I need to do this every time on a different mashine.
    So my question is: Can I do this with Doctrine Migrations, when I already have an existing Entity? How can I "teach" Doctrine Migrations to replace the string in the old Post-table with the correct id from the new Entity?

  • 2016-06-14 JLChafardet

    I cant believe it! wow

    @ORM\ManyToOne(targetEntity="EntityName") <- SERIOUSLY?????? what have I done this past years? oh gawd, gimme my time back.

    ..... i want to go cry in a corner for a long while

  • 2016-06-14 weaverryan


    Yep, this is a perfect case for OneToOne. I dismiss OneToOne here, because OneToOne is really the same in the database as a ManyToOne, except that Doctrine makes user_id on the profile table unique, to prevent you from creating multiple. I want people to focus on the big two: ManyToOne and ManyToMany. Also, sometimes, OneToOne can give you more work. In this example, you *could* simply just put all the field on Profile onto User, and eliminate the complexity. Of course, then the User table becomes bigger and bigger, so splitting this into a OneToOne situation is legitimate (but sometimes I see people over-doing this and adding complexity for no benefit).

    So yes, you're in find shape :)

  • 2016-06-14 the_nuts


    I have an Entity User (with id, username, email, is_active, and other most used parameters)
    and another entity Profile (with personal info such as first and last name, address, etc... which are rarely used in the application)
    The PK ot the table profiles should be user_id, with as FK.

    Can't I use OneToOne in this case?

  • 2016-05-31 weaverryan

    Hey Dan!

    Wow, you have a *very* good attention for detail! The truth is that nothing has changed - OneToMany still exists. In truth, you only *need* ManyToOne and ManyToMany. OneToMany is an optional way to look at a ManyToOne relationship. So really, ManyToOne and OneToMany are the *same* relationship, just looked to from different sides. So, I like to tell people initially just to worry about ManyToOne and ManyToMany. Later, we will learn about OneToMany, but it isn't really a true, new relationship type.

    Also, there is another - OneToOne. But again, this is *really* just a ManyToOne (it looks the same in the database), but Doctrine helps you to guarantee that you only link one object to one other object. There is limited use for this relationship in my opinion, so I save it for later :).

    Short answer: there is no difference! Just me simplifying how we explain this.


  • 2016-05-27 Dan Costinel

    Hey Ryan,

    I'm having the old video, the one presented by Leanna, in which she says there are 3 (three) types of relationships: ManyToOne, ManyToMany and OneToMany. I know her version of Symfony, back then, was 2.4, and now, you are presenting this tutorial for Symfony 3, with just 2 (two) types of relationships: ManyToOne and ManyToMany.

    My question: the difference between the number of relationships is because of the Symfony different versions?

    Thank you.

  • 2016-03-23 weaverryan

    Hopefully this week - but definitely by next week :)

  • 2016-03-23 Andrew Grudin