Saving Many to Many relationship to database in Symfony2

Stefanie Delchambre picture Stefanie Delchambre · Jan 4, 2013 · Viewed 19.6k times · Source

In my Symfony2 project I have two related entities: Users and Favorites. They have a many-to-many relationship.

My application works as follows: In my Twig-page I have an few items with a button 'Add to Favorites'. When you click the button my controller saves the item_id in the Favorites column. But then I want to save the user who added the item to his favorites and here my application fails.

The User and the favorite exist but the joincolumn between Users and Favorites remains empty. I also don't receive any kind of errors.

Here is my code:

Entity Users

class Users implements AdvancedUserInterface
{
    /**
     * @var \Doctrine\Common\Collections\ArrayCollection
     *
     * @ORM\ManyToMany(targetEntity="Favorites", inversedBy="user", cascade={"persist"})
     * @ORM\JoinTable(name="user_has_favorite",
     *   joinColumns={
     *     @ORM\JoinColumn(name="user_id", referencedColumnName="user_id")
     *   },
     *   inverseJoinColumns={
     *     @ORM\JoinColumn(name="favorite_id", referencedColumnName="favorite_id")
     *   }
     * )
     */
    private $favorite;

    public function __construct()
    {
        $this->favorite = new \Doctrine\Common\Collections\ArrayCollection();
    }

    public function addFavorite(\Geo\CityTroopersBundle\Entity\Favorites $favorite)
    {
        $this->favorite[] = $favorite;

        return $this;
    }
...

Entity Favorites

class Favorites
{

    /**
     * @var \Doctrine\Common\Collections\ArrayCollection
     *
     * @ORM\ManyToMany(targetEntity="Users", mappedBy="favorite", cascade={"persist"})
     */
    private $user;

    public function __construct()
    {
        $this->user = new \Doctrine\Common\Collections\ArrayCollection();
    }
    public function addUser(\Geo\CityTroopersBundle\Entity\Users $user)
    {
        $this->user[] = $user;    
        return $this;
    }

My controller

public function showNewsAction()
    {
        $request = $this->get('request');    
        $itemId=$request->request->get('itemId');
        if($itemId != NULL)
        {
        //MAKE NEW FAVORITE AND ADD TO DATABASE LINKED WITH ITEM
        $favorite = new Favorites();
        $favorite->setItemId($itemId);

         //LINK FAVORITE ID WITH USER ID IN JOINCOLUMN
        $userId = 6;
        $em = $this->getDoctrine()->getEntityManager();

        $user = $em->getRepository('GeoCityTroopersBundle:Users')->find($userId);

        $favorite->addUser($user);
        $em->persist($favorite); 

        //I TRIED THIS TOO, BUT IT FAILED
        /*$user->addFavorite($favorite);
        $em->persist($user);*/

        $em->flush();

Answer

Squazic picture Squazic · Jan 4, 2013

You were close there. For doctrine many-to-many relationships, you need to call both add methods

$favorite->addUser($user);
$user->addFavorite($favorite);

$em->persist($favorite); 
$em->persist($user);
$em->flush();

This should do the trick. In the docs they do this, but don't mention it too explicitly. Not sure why either because lots of people run into this (myself included).