Doctrine not saving ManyToMany

Say you have a ManyToMany relationship, like Post <—> Tag.

When you add tags to a Post and the save the Post, everything is great. But when you add posts to a Tag and then save the Tag, the posts are not saved. Why? Because Doctrine persists changes only on the owning side of a relation. The owning side is the one that has the inversedBy.

How to fix this? Simple. If you’re accessing the Entity directly (without a Symfony form), then there is only 1 step.

1. On the inverse side (Tag), you will need to edit the following methods: addPost and removePost.

This will keep the owning side in sync, so that persisting either the Post or the Tag will save the association. At this point, you can go ahead and clean up the cascade in the Tag entity, as it’s no longer necessary.

2. If you’re using a Symfony form with a collection field to associate the posts, you need to add an extra option in your form builder:

This is only needed in the Tag form (the inverse side of the relationship). If you omit this option, it will default to true and will set posts by reference. It will go fetch the ArrayCollection of posts and manipulate it directly, therefore not calling addPost/removePost that you need to keep things in sync. Setting this option to false will force the form to call these methods.

Happy coding!

14 thoughts on “Doctrine not saving ManyToMany

  1. OMG thanks a lot! The moment I read owning sides I immediately knew what I was doing wrong. I put the owning side on the wrong entity, didn’t notice it and therefore had been rereading my code like forever. DOH! Must be time for weekend…. Thanks again!

    • Glad to be helpful. Have a good and relaxing weekend 🙂

  2. Thanks you a lot! Great post!

  3. Agustín Houlgrave

    Thanks! Just what i needed!

  4. mboy

    Hi

    what happens if Tag belong to 2 different Posts (Post1, Post2) and i delete one of them (Post1)?
    wouldn’t cascade=remove cause the Tag to be deleted as well and therefore remove the connection between Tag and Post2?

  5. mboy

    as per this answer http://stackoverflow.com/questions/24612664/understanding-doctrine-cascade-operations using cascade=remove on ManyToMany is wrong

  6. Viktor

    Thanks a lot. Doctrine doen’t genrated (I assume Your code is mine:))
    $post->addTag($this);
    in addPost method. Therefore i had a message that tag_id is null. And after i added this line it started working!

    Thanks a lot!

  7. I can’t believe this is an issue. I’ve spent 45 mins looking for a solution and this is the only one I found that worked. Well done Anna.

    Doctrine / Symfony don’t even seem to share this little snippet.

  8. Mikael Brosset

    I love you for this article

  9. Roland

    Thank you Anna, your article saved a lot of time for me today !

  10. Gabriel

    Muchas gracias!!! <3

  11. Muhammad Bilal

    Thank you very much.you saved my lot of time .

  12. Rolf

    Thanks a lot Anna, you made my day !!!

Leave a Reply

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

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">