[英]Doctrine2 one-to-many relation overwrite whole collection
假設我有兩個實體Page和Block。 這是雙向映射。 每個頁面可以包含多個塊。 每個塊可以屬於單個頁面。
/**
* @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
在第二次flush()調用之后的預期結果是://頁面將具有1、4
因此,我需要使用merge方法完全覆蓋塊的集合。
約束:
是否可以通過注釋或其他技巧來實現所需的結果?
它不能用您的約束來完成。
我會在BlockRepository類中創建一個自定義函數,該函數刪除給定Page的所有塊,然后在調用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()
這是管理經常更改的項目的常見模式。 它不需要循環。
如果約束是自我施加的,那么您需要放寬它們並找到另一種解決方案,例如我上面提供的解決方案。 如果他們是一些上流人士施加的限制,那么現在是時候與他/她進行對話,討論這種對話在這種情況下會適得其反。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.