web-dev-qa-db-ja.com

Symfony2のデータベースへの多対多の関係の保存

私のSymfony2プロジェクトには、ユーザーとお気に入りの2つの関連エンティティがあります。彼らは多対多の関係を持っています。

私のアプリケーションは次のように機能します。Twigページには、[お気に入りに追加]ボタンのあるアイテムがいくつかあります。ボタンをクリックすると、コントローラーはitem_idを[お気に入り]列に保存します。しかし、アイテムをお気に入りに追加したユーザーを保存したいのですが、ここでアプリケーションが失敗します。

ユーザーとお気に入りは存在しますが、ユーザーとお気に入りの間の結合列は空のままです。また、エラーは発生しません。

これが私のコードです:

エンティティユーザー

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;
    }
...

エンティティのお気に入り

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;
    }

私のコントローラー

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();
18

あなたはそこに近かった。 doctrine多対多の関係の場合、両方のaddメソッドを呼び出す必要があります

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

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

これでうまくいくはずです。 docs でこれを行いますが、あまり明示的に言及しないでください。多くの人がこれに遭遇するので(私自身も含めて)、理由もわかりません。

24
Squazic

ここで説明するように、接続管理は所有側のみが担当します: http://doctrine-orm.readthedocs.org/en/latest/reference/association-mapping.html#owning-and-inverse-side -on-a-manytomany-association

だからだけ

$user->addFavorite($favorite);

持続するべきであり、

$favorite->addUser($user);
8
Cedric

あなたのラインで:

@ORM\JoinColumn(name="favorite_id", referencedColumnName="favorite_id")

ザ・

name="favorite_id"

一部は結合テーブルの列を参照しますが、

referencedColumnName="favorite_id"

通常は単に「id」であるお気に入りのテーブルのIDを指します。試してみてください :

    /**
 * @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="id")
 *   },
 *   inverseJoinColumns={
 *     @ORM\JoinColumn(name="favorite_id", referencedColumnName="id")
 *   }
 * )
 */
private $favorite;
0

セドリックが示したように、多対多の関係のレコードの追加は一方向でのみ行われ、関係の定義方法によって異なります。追加は関係の親エンティティによってのみ実行できるため、この場合は:

$user->addFavorite($favorite);
0
B. Assem