Doctrine Collections: ManyToMany, Forms & other Complex Relations

Buy Access

Tip: This course is built on Symfony 3, but most of the concepts apply just fine to Symfony 4.

With the basic of Doctrine relations behind us, it's time to dive deeper and get our hands dirty with some real-world, but complex collections. Honestly, this is the hardest part of Doctrine: so let's get it right:

  • Creating ManyToMany associations
  • Querying on ManyToMany relations
  • Mapping the inverse (collection) side of a relation
  • (bonus) Using DoctrineExtension for clean URL slugs
  • Keeping the owning & inverse sides in-sync
  • Using orphanRemoval to delete items in a collection
  • Using cascade to save items in a collection
  • Counting collections in the EXTRA_LAZY way
  • Rendering relationship data from both sides
  • Filtering collections efficiently with Criteria (mind will be blown)
  • Dealing with complex collection forms
  • Adding "extra" data to the "join table"

Doctrine relationships take a little bit more work to get setup. So let's master this stuff, setup our relationships to win, and get back to work.

Your Guides

Ryan Weaver

Questions? Conversation?

  • 2017-03-21 Diego Aguiar

    Hey Julien!
    I'm glad to hear it
    If you have any more questions don't hesitate to contact us :)

  • 2017-03-20 julien moulis

    Hey Diego! Thanks for reply. Finally I used Blameable

  • 2017-03-17 Diego Aguiar

    Hey Julien!

    Indeed there are many ways of doing it, but I preffer using a setter because its more explicit in what are you doing.
    Also there is a Doctrine Extension that might help you "Blameable"
    it works like magic via annotations, some guys doesn't like it because it hides details, like in your case, the user must be the logged in user, but that's up to you :)

    Blameable info link:

  • 2017-03-17 julien moulis

    Hi. I would like to know if you could give me a piece of advice. I have followed the symfony track and still have a question about mantTomany relation. I have 3 entities user, ticket. I created a third entity "answers" with user id and ticket id as a foreign key and two attributes (message, datecreated). My pb is that when a create a new answer it persists properly in the database with the right ticket id but I can't make the user id which has to be the actuel logged user persist in the database. So I was wondering what would be the best way... FormEvent, DoctrineEvent, directly in the setter of the answer entity, controller... AHHHHH I'm lost... I probably spent much more time eating cookie and watching turtles pictures than listen the course ;-)

  • 2016-12-02 weaverryan

    Haha, that just made my night ;)

  • 2016-12-02 Micheal

    I don't know how you have the time to do all of this, but cheers. :)

  • 2016-11-10 weaverryan

    Hey Vince!

    Hmm, I don't quite understand the setup. I assume that each Product is related to one ProductCategory, correct? And the ProductCategory has "tags"? Or are speed, capacity and screen resolution properties on the ProductCategory? I wasn't clear on that :). And also, is the ProductCategory used to determine the data/fields needed for the Product? I mean, if a Product is related to ProductCategory A, then it will have data for speed, capacity and screen resolution. But if a Product is related to a ProductCategory B, then it may have data for color, width, and height? Is this what your requirements are?

    If so, it's a difficult problem to solve, because basically: this doesn't fit well into a relational database. Some people use a no-SQL database for this, or, more commonly, they use a pattern called EAV, which is a way of organizing data into a relational database that allows for "random" fields to be added to a Product for example. It's fairly simple in some sense, but can also be really inefficient... but it's really the only way to solve the problem (unless you know that you will have a static, small number of categories - e.g. you will always have only 5 categories, then we could create 5 different entities for these).

    Let me know! Cheers!

  • 2016-11-09 Vince Liem

    Hi. I'm wondering what would be the best practice of making an entity about products, product categories and product specifications. For example giving a product category tags like (speed, capacity, resolution screen) and a product that is bound to that category, its values for those tags. But now I have a product category entity with tag1, tag2, tag3 to a max of 15. I know that there must be a better way.

  • 2016-11-09 Hermen

    YES, we're off!!!

  • 2016-11-07 weaverryan

    Yo xdrew!

    Yes! And no! And maybe :). We show using the EntityType with a ManyToMany for checkboxes. And then, we later show the CollectionType with add/remove features once that relationship gets a bit more complicated and has extra fields. So, I'm *pretty* sure we'll be covering exactly what you're looking for :). It'll start coming out this week.


  • 2016-11-07 xdrew

    I wonder if it possible to render many to many relation as checkboxes (EntityType attributes) but with CollectionType-specific add/remove features? Will that case be covered with this tutorial?)

  • 2016-11-03 weaverryan

    This tut is in the editing phase! It will likely start releasing next week :)

  • 2016-11-02 Hermen

    Ooh yeh, almost...

  • 2016-10-07 Victor Bocharsky

    Well, we're working on this course, Ansible for Automation! and Design Patterns from Space. Most probably they'll be released in the same order I mentioned. That's it for now :)


  • 2016-10-07 Greg

    Hey Victor,

    Thanks for your answer.
    I already subscribed to this course a long time before I asked ;)

    Do you have a schedule about the next courses ?
    Thanks again

  • 2016-10-06 Victor Bocharsky

    Hey Greg,

    Thank you for kind words! This course in progress right now and most probably it will be released in October/November. You can subscribe to this course and we'll notice you when it happened.


  • 2016-10-06 Greg


    Any idea when this tutorial will be available?

    Thanks for your awesome job ;)