0 レビュー
1 回答
php-Doctrine21対多の関係がコレクション全体を上書きします
PageとBlockの2つのエンティティがあるとします。それは双方向のマッピングです。各ページには複数のブロックを含めることができます。各ブロックは単一のページに属することができます。
/**
* @ORM\Entity
* @ORM\Table(name="page")
*/
class Page
{
...
/**
* @ORM\OneToMany(targetEntity="Block", mappedBy="page", cascade={"all"}, orphanRemoval=true)
**/
private $blocks;
...
}
/**
* @ORM\Entity
* @ORM\Table(name="block")
*/
class Block
{
...
/**
* @ORM\ManyToOne(targetEntity="Page", inversedBy="blocks")
* @ORM\JoinColumn(name="page_id", referencedColumnName="id")
*
**/
private $page;
...
}
ページに属するブロックは随時変更されます。一部のブロックが追加され、一部が削除されます。次のケースは私にはうまくいきません:
$page->setBlocks([1, 2, 3]);
$em->merge($page)
$em->flush() //Page will have blocks 1, 2, 3
$page->setBlocks([1, 4])
$em->merge($page)
$em->flush() //Page will have blocks 1, 2, 3, 4
2回目のflush()呼び出し後の期待される結果は次のとおりです。//ページは1、4になります
したがって、ブロックのコレクションをマージメソッドで完全に上書きする必要があります。
制約:
- PageクラスにdeleteBlockを実装できません
- $ emでのみmerge()とflush()を呼び出すことができます
注釈やその他のトリックを介して目的の結果を実装することは可能ですか?
わからない
0
レビュー
答え :
解決策:
制約への対処
制約を使用して実行することはできません。
推奨される解決策
指定されたページのすべてのブロックを削除するカスタム関数をBlockRepositoryクラスに作成し、setBlock関数を呼び出す前にその関数を呼び出します。
これをブロックリポジトリクラスに追加します:
public function deleteBlocksByPageId($page_id)
{
$qb = $this->createQueryBuilder()
->delete('Block', 'b');
->where('b.page', ':page'));
->setParameter(':page', $page_id);
$numDeleted = $qb->execute();
return $numDeleted;
}
コントローラー内:
//Delete all the existing blocks before adding them back in.
$repo = $this->getDoctrine()->getRepository('BundleName:BlockRepository');
$repo->deleteBlocksByPageId($page->getId());
$page->setBlocks([1, 4])
$em->merge($page)
$em->flush()
結論
これは、頻繁に変更されるアイテムを管理するための一般的なパターンです。ループは必要ありませんでした。
制約が自主的に課せられている場合は、制約を緩めて、上記のような別の解決策を見つける必要があります。それらが上層部によって課せられた制約である場合は、この場合は逆効果であることについて彼/彼女と話し合う時が来ました。
わからない
同様の質問
私たちのウェブサイトで同様の質問で答えを見つけてください。