web-dev-qa-db-ja.com

Symfony2Doctrine2多対多の形式でエンティティを保存しない

多対多の関係で問題が発生しています。 UsersAssetsがあります。アセットページでユーザーをアセットに割り当てられるようにしたいと思います。

以下のコードは、アセットを作成/編集するときにユーザーのリストを表示しますが、ユーザーのチェックボックスに加えられた変更は保存されず、残りのデータは保持されます。

Mysqlクライアントを介してusers_assetsにエントリを追加すると、これらの変更がアセットリストに表示されます。

ユーザー

class User extends BaseUser
{
    /**
     * @ORM\ManyToMany(targetEntity="Asset", inversedBy="users")
     */
    private $assets;
}

アセット

class Asset
{
    /**
     * @ORM\ManyToMany(targetEntity="User", mappedBy="assets")
     */
    private $users;
}

AssetType

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $form = $builder
        ->add('users', null, array(
            'expanded' => true,
            'multiple' => true
        ))
        ->getForm();

    return $form;
}
21
Shawn Northrop

何らかの理由で、これを機能させるためにdoctrineマッピングを切り替える必要がありました:

Asset:
 /**
 * @ORM\ManyToMany(targetEntity="Adaptive\UserBundle\Entity\User", inversedBy="assets")
 * @ORM\JoinTable(name="user_assets")
 */
private $users;

User:
 /**
 * @ORM\ManyToMany(targetEntity="Splash\SiteBundle\Entity\Asset", mappedBy="users")
 */
private $assets;

アセットを保存すると、関連付けられているユーザーが保存されます。ビルダー->追加をエンティティまたはコレクションとして定義する必要はありませんでした。 nullを渡すだけで、マッピング情報を使用してエンティティ情報を入力します。

AssetType:
->add('users', null, array('expanded' => "true", "multiple" => "true"))

アセットとユーザーのinversedByとJoinTableの情報が必要な理由は正確にはわかりませんが、現在は機能しているようです。

提案をありがとう!!!

32
Shawn Northrop

アセットとユーザーのinversedByとJoinTableの情報が必要な理由は正確にはわかりませんが、現在は機能しているようです。

変更が無視された理由は、doctrineは、リレーションの所有側による変更のみを保持するためです(@Florianが言ったように)。

これは、この動作が説明されているDoctrineのドキュメントへのリンクです: http://docs.doctrine-project.org/en/latest/reference/unitofwork-associations.html

17
naitsirch

奇妙なことに、私は2016年に同じ問題に直面しましたが、それでも解決策を見つけるのに苦労しました。私は将来のグーグルのためにそれを共有します:

問題は、フォームを保存するときにsymfonyが本質的に行うことは次のとおりです。

$asset->getUsers()->add($user)

そして、あなたは関係の反対側にいるので、あなたの変更は持続しません。

本当に必要なのは、これを呼び出すように作成することです。

$asset->addUser($user)

AddUser()がアセットエンティティで次のように定義されている場合:

_public function addUser(User $user) 
{
    //add to the inverse side
    $this->users->add($user);

    //add on the owning side (only this is persisted)
    $user->addAsset($this); //$user->assets->add($asset);
}
_

したがって、symfonyにその$asset->addUser()メソッドを使用させるには、次のように設定する必要があります。

_'by_reference' => false_

usersフォームのAssetTypeフィールド。

この設定の詳細はこちら http://symfony.com/doc/current/reference/forms/types/form.html#by-reference

同じ方法でremoveUser()メソッドも定義する必要があることを忘れないでください(所有関係からエンティティを削除するため)

17
Pavel Dubinin

最初に、注釈に円記号の接頭辞をドロップする必要があります(通知 ここ を参照)。

また、エンティティフィールドタイプを使用する必要があります。

$builder->add('users', 'entity', array(
    'class' => 'AdaptiveUserBundle:User',
    'expanded' => true,
    'multiple' => true,
    'query_builder' => function(EntityRepository $er) {
        return $er->createQueryBuilder('u')
            ->orderBy('u.username', 'ASC');
    },
));
4
jkucharovic

フォームでは「コレクション」フィールドタイプを使用する必要があります。

_$builder->add('users', 'collection', array(
    'type' => new UserType(),
    'prototype' => true,
    'allow_add' => true,
    'allow_delete' => true
));
_

明らかに、最初にUserType()フォームを作成する必要があります。

コードサンプルを含む、必要なすべての情報を以下に示します。

http://symfony.com/doc/current/cookbook/form/form_collections.html

http://symfony.com/doc/current/reference/forms/types/collection.html

0
grzechoo