3

私はSymfony2.0.17-DEVとPHP5.3.14でDoctrine2.2.2を使用しています。カスケードオプションとの多対多の関連付けに問題があります。例はとても単純です、この素晴らしいボードの誰かが私を助けることができるよりも願っています。

とにかく、Metaスーパークラスはとの関係の所有者ですUser。関連するフィールドとコンストラクターのみ:

abstract class Meta
{
    /**
     * @ORM\ManyToMany(targetEntity="User", inversedBy="meta")
     * @ORM\JoinTable(name="meta_users",
     *     joinColumns={@ORM\JoinColumn(onDelete="CASCADE")},
     *     inverseJoinColumns={@ORM\JoinColumn(onDelete="CASCADE")}
     * )
     */
    protected $users;

    public function __construct()
    {
        $this->users = new ArrayCollection();
    }

    public function addUser(User $user)
    {
        $this->users[] = $user;
        return $this;
    }

    public function getUsers()
    {
        return $this->users;
    }
}

(実装、空のクラス、areLabelおよびCategory

シンプルで、実際に機能します。つまり、メタからユーザーを追加または削除すると、結合テーブルの対応する行が実際に追加/削除されます。

問題は、ユーザーの作成/編集とメタの割り当てという逆の方法で発生します。Userこの方法でメタとの関連付けを定義し、cascade="all"オプションを追加します。

class User
{
    /**
     * @ORM\ManyToMany(targetEntity="Meta", mappedBy="users", cascade={"all"})
     */
    protected $meta;

    public function __construct()
    {
        $this->meta = new ArrayCollection();
    }

    public function addMeta(Meta $meta)
    {
        $this->meta[] = $meta;
        return $this;
    }

    public function getMeta()
    {
        return $this->meta;
    }
}

私はDoctrineにまったく慣れていませんが、これは機能していません。を作成/編集するための私のSymfony2フォームに、すべてのメタを選択するだけ Userで、タイプのフィールドを追加しました。entity

$builder
    ->add('meta', 'entity', array(
        'label'         => 'Meta',
        'class'         => 'Acme\HelloBundle\Entity\Meta',
        'property'      => 'select_label',
        'multiple' => true,
        'expanded' => true,
    ))
;

(チェックボックスを使用して)メタをユーザーに割り当てる場合、テーブルに変更はありません。どうしたの?何かが足りないと思いますが、何が見つかりません。

4

1 に答える 1

1

私が知っていることを話してください。

カスケード オプションは、結合テーブルの関連付けの永続化とは関係ありません。エンティティの関係で新しいMetaエンティティが見つかった場合(または古いエンティティが削除された場合) に使用する必要があります。それは、フォームに入力を追加して、新しいメタを作成するか、既存のメタを削除する場合です。たとえば、Symfony 2 が提供する for フィールド タイプを使用します)。または、あなたがそうするときだけ:metaUsercollection

$newMeta = new Meta();

$user->addMeta($meta);

$em->persist($user); // A new entity was found in the relation meta

私が理解している限り、関係自体を永続化したいと考えています。Doctrineは、エンティティを永続化するために常に所有側を探します。言えば、対応するチェックボックスがオンになっているかどうかにかかわらず、ユーザーを追加または削除する各メタを永続化するよりも、最初にユーザーを永続化したいということです。

フィールドはentityタイプです。つまり、すべてのメタがテーブルから取得され、ユーザーに既に割り当てられているメタはチェック済みとしてマークされます。

同様のことをしたことを覚えています。これは「疑似」コントローラーコードです。

$em->persist($user); // Perstist the inverse side

// This is what user selected
$selectedMeta = $user->getMeta();

// All meta coming from your database
$allMeta = $em->getRepository('YourBundle::Meta')->find();

// Loop on the owning side
foreach($allMeta as $meta)
{
    // Is current meta selected?
    $isSelected = $selectedMeta->contains($meta);

    // Does this meta have already the user in it?
    $hasUser = $meta->getUsers()->contains($user);

    // To be removed: not selected and with the user
    if(!$isSelected && $hasUser)
        $meta->getUsers()->removeElement($user);

    // To be added: selected and without the user
    if($isSelected && !$hasUser)
        $meta->addUser($user);

    $em->persist($meta); // Persist the owning side and the association
}

// Apply
$em->flush();

こちらも確定待ち!

于 2012-08-05T05:24:13.320 に答える