5

イベントの多対多関係の変化を検出しようとしていますonFlush

新しいエンティティがリレーションに追加された場合、またはリレーションが更新された場合 (常に要素を保持)、 を使用して変更を検出し、または$unitOfWork->getScheduledCollectionUpdates()をチェックできます。ここまでは順調ですね。getInsertDiff()getDeleteDiff()

問題は、関係からすべてのエンティティを取り出すときに発生します。「以前は 2 つの関連エンティティがありましたが、現在は関連エンティティがありません。」

リレーションを空のままにすると にアクセスできます$unitOfWork->getScheduledCollectionDeletions()が、どのエンティティが削除されたかを知る方法はありません。

  • getDeleteDiff()このコレクションでは何もわかりません。
  • getSnapshot()以前にどのエンティティがあったかはわかりません

どのエンティティが多対多の関係から除外されたかを知るにはどうすればよいですか?


完全な実装で Gist を追加しました: $uow->getScheduledCollectionDeletions()(101 行目) を除いて、すべて正常に動作します (最適化が必要な場合があります) 。

https://gist.github.com/eillarra/5127606

4

1 に答える 1

9

この問題の原因は 2 つあります。

1) メソッドclear()が で呼び出されるとDoctrine\ORM\PersistentCollection、次のようになります。

  1. エンティティの内部コレクションをクリアします。
  2. を呼び出しscheduleCollectionDeletion()ますDoctrine\ORM\UnitOfWork
  3. それ自体の新しいスナップショットを取得します。

番号 2 は、あなたのコレクションが$uow->getScheduledCollectionDeletions()(ではなく$uow->getScheduledCollectionUpdates()) に表示される理由です。番号 3 は、クリアされる前にコレクションに何があったかを判断できない理由です。

2) Symfony2 Form コンポーネントを使用する場合、具体的にはChoiceTypeまたはCollectionTypeタイプを option と組み合わせて使用​​すると、コレクションからすべてのエンティティを削除する必要があるときにmultiple、そのclear()メソッドが呼び出されます。

これは、httpsMergeDoctrineCollectionListener ://github.com/symfony/symfony/blob/master/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php#L55 に追加されている ためです。

これは最適化として行われます。どのエンティティをコレクションから削除する必要があるかを確認するよりも、この方法でコレクションをクリアする方が高速です。

私は2つの可能な解決策を考えることができます:

1) を追加しないように、フォークを作成しsymfony/symfony、オプションを実装します。リスナーが追加されないようにするようなものかもしれません。すべてのエンティティを削除する必要があるときにコレクションのメソッドが呼び出されないため、これにより BC ブレークが発生せず、問題が解決されます。MergeDoctrineCollectionListenerno_clearclear()

OnLoad2) カウンターを再設計します:データベースからフェッチされた時点でコレクション内のエンティティの量をカウントできるイベントもリッスンします。そうすれば、OnFlushリスナーはその数を使用して、コレクションがクリアされたときにコレクションから削除されたエンティティの数を知ることができます。

于 2013-03-13T19:05:53.950 に答える