symfony - 如何在多个级别上更新实体及其关系?
问题描述
我正在使用 Symfony 3 和 Doctrine 制作一个 Web 应用程序,它允许绘制树结构并将其持久化。
一个节点包含名为 的OneToMany
关系children
中的子节点,树的根是唯一不是任何其他节点的子节点的节点。
这是实体:
/**
* @ORM\Entity(repositoryClass="App\Repository\NodeRepository")
*/
class Node
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
public $id;
/**
* @ORM\Column(type="string", length=255)
*/
public $name;
/**
* @ORM\OneToMany(targetEntity="App\Entity\Node", mappedBy="parent")
*/
public $children;
/**
* @ORM\ManyToOne(targetEntity="App\Entity\Node", inversedBy="children")
* @ORM\JoinColumn(name="id_parent", referencedColumnName="id")
*/
public $parent;
public function __construct()
{
$this->children = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
/**
* @return Collection|Node[]
*/
public function getChildren(): Collection
{
return $this->children;
}
public function addChild(Node $child): self
{
if (!$this->children->contains($child)) {
$this->children[] = $child;
$child->setParent($this);
}
return $this;
}
public function removeChild(Node $child): self
{
if ($this->children->contains($child)) {
$this->children->removeElement($child);
// set the owning side to null (unless already changed)
if ($child->getParent() === $this) {
$child->setParent(null);
}
}
return $this;
}
public function getParent(): ?self
{
return $this->parent;
}
public function setParent(?self $parent): self
{
$this->parent = $parent;
return $this;
}
}
创建一棵树我没有特别的问题。但是在更新它时,我不确定最好的方法是什么。主要示例是删除一个节点(但该问题也适用于移动节点),我将进一步说明我的问题。
我有一个updateNodeAction
控制器,它将整个新树作为参数(整个结构都设置了学说 ID)。我想要merge
具有已经持久化的传入树,以便在执行flush
.
在我的梦中,我想象类似的东西(参数$node
是设置了 id 的根节点):
public function updateNodeAction(Node $node, EntityManagerInterface $entityManager) {
$entityManager->merge($node);
$entityManager->flush();
return new Response('OK');
}
Doctrine 处理对数据库中节点本身及其所有后代(添加、删除、移动)的所有修改。例如,如果以下根的 id 为 1 的树已经保存在数据库中
然后我用以下一个调用我的更新控制器(当然尊重ID)
Doctrine 将能够“看到”新结构中缺少节点 5,然后$entityManager->remove($node5)
自行执行。
这不是一个梦想吗?有某种方法可以让 Doctrine 表现得像这样吗?或者我是否必须递归地向下树并进行逐节点比较才能通过entityManager
自己进行修改?
解决方案
我得出的结论是教义没有那么神奇;)
所以我不得不:
merge
声明沿关系传播的 Doctrine操作children
(带有cascade={"merge"}
注释)merge
根节点$em->remove
在合并之前存在于树上的节点上调用操作,并且在传入树上不存在- 最后,打电话
$em->flush
推荐阅读
- excel - 结果长度为 19 的数学结果的 Dart 计算或舍入误差?
- trace32 - Coresight TMC 识别错误是什么意思?
- shopify - 页面源代码中的 hreflang 冲突
- javascript - 如何转换网页上的 SQL 数据,使任何作为 URL 的数据都变成超链接?
- css - 滚动时如何使元素粘在屏幕顶部
- java - 为什么在打印奇偶条件后,我没有通过扫描仪从字符串变量“str”获取输入?
- reactjs - 通过 React-Router v5 Link 传递对象
- amazon-web-services - AWS Systems Manager Explorer 数据通过 CLI 检索
- android - 为什么我们在 Kotlin 用例中使用调用运算符重载?
- android - 如何使用接口将数据从片段传递到回收器视图