Doctrine ManyToMany 自引用双向 - 父级未更新
Posted
技术标签:
【中文标题】Doctrine ManyToMany 自引用双向 - 父级未更新【英文标题】:Doctrine ManyToMany self referencing bidirectionnal - Parent not updated 【发布时间】:2018-03-27 13:07:37 【问题描述】:我正在尝试创建公司的多对多关系 beetwin 服务。 每个服务都有 N 个父母 服务和 N 个孩子 服务。
我在这里查看了教义文档:Many-To-Many, Self-referencing,并按如下方式实现了它:
这是我的服务实体:
<?
namespace AppBundle\Entity;
class Service
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Service", mappedBy="enfants", cascade="persist")
*/
private $parents;
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Service", inversedBy="parents")
* @ORM\JoinTable(name="app_services_hierarchy",
* joinColumns=@ORM\JoinColumn(name="parent_id", referencedColumnName="id"),
* inverseJoinColumns=@ORM\JoinColumn(name="enfant_id", referencedColumnName="id")
* )
*/
private $enfants;
public function __construct()
$this->enfants = new ArrayCollection();
$this->parents = new ArrayCollection();
public function getId()
return $this->id;
//--------------------------------------------------Enfants
public function getEnfants()
return $this->enfants;
public function setEnfants($enfant)
$this->enfants = $enfant;
public function addEnfant(Service $s)
$this->enfants[] = $s;
return $this;
public function removeEnfant(Service $s)
$this->enfants->removeElement($s);
//--------------------------------------------------Parents
public function getParents()
return $this->parents;
public function setParents($parents)
$this->parents = $parents;
public function addParent(Service $s)
$this->parents[] = $s;
return $this;
public function removeParent(Service $s)
$this->parents->removeElement($s);
这是我的编辑功能(Controller.php):
public function editAction(Request $request, $id)
$service = $this->getDoctrine()->getRepository(Service::class)->find($id);
$form = $this->createForm(ServiceType::class, $service);
$form ->handleRequest($request);
if ($form->isSubmitted() && $form->isValid())
$entityManager = $this->getDoctrine()->getManager();
$entityManager ->persist($service);
dump($service);
$entityManager ->flush();
return $this->render('AppBundle:Service:edit.html.twig', array(
'form' => $form->createView(),
));
生成的表单如下所示:
问题:
我的问题是 孩子更新了,但父母没有更新。当我在控制器中 dump()
时,我可以在 $service
变量中看到父级,但在我的数据库表 (app_services_hierarchie) 中更新的唯一是子级。
【问题讨论】:
看看***.com/questions/5033825/… 可能是这样,但它仍然无法正常工作......奇怪的是,当我更新时,表单被重新加载,我之前选择的父母被选中(所以我的实体充满了父母)但数据库中没有任何内容,所以一旦我重新加载页面它们就会消失...... 【参考方案1】:您的代码中$parents
和$enfants
之间的区别在于,在您的$enfants
映射的情况下,您正在查看的服务是拥有方,但在你的$parents
映射。
Doctrine 不会存储 $parents
,除非您通过 cascade="persist"
告诉它这样做。
/**
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Service", mappedBy="enfants", cascade="persist")
*/
这与@GregoireDucharme 链接的帖子中给出的答案基本相同。
编辑:经过一番研究,显然这个问题不能使用级联解决。根据Doctrine documentation:
Doctrine 只会检查关联的拥有方是否有更改。
所以你要做的就是告诉你的$parents
也更新$children
属性。
public function addParent(Service $s)
$this->parents[] = $s;
$s->addEnfant($this);
return $this;
public function removeParent(Service $s)
$this->parents->removeElement($s);
$s->removeEnfant($this);
在您的表单中,确保指定以下内容:
->add('parents', 'collection', array(
'by_reference' => false,
//...
))
(我没有对上面的任何代码进行拼写检查,所以请谨慎行事。)
如果'by_reference'
设置为true
,addParent
和removeParent
将不会被调用。
感谢 Anny Filina 的 blog post。
它还指出您可以从您的$parents
属性中删除cascade
选项,但您可能应该将cascade="persist","remove"
添加到您的$enfants
属性中。
【讨论】:
我之前尝试过这个解决方案,但它仍然无法正常工作,实体已更新但数据库未更新。数据库刚刚为儿童(儿童)更新/我编辑了我的问题以添加级联持久性(即使它不起作用,你们都告诉我添加它,我可能是解决方案的一部分,这很有意义) 您是否也尝试过添加refresh
? cascade="persist", "refresh"
。真的不确定这是否与“更新”实体有关,但值得一试。
@Gauthier 编辑了我的回复。看起来该位置的 cascade
选项不是您正在寻找的解决方案。
我想我已经很接近了,当我尝试更新时收到错误“Expected argument of type "AppBundle\Entity\Service", "string" given",并且没有显示表单不再作为选择列表。我觉得我更近了。无论如何感谢您查看此内容,我认为您找到了问题@micha以上是关于Doctrine ManyToMany 自引用双向 - 父级未更新的主要内容,如果未能解决你的问题,请参考以下文章
为啥这个 Doctrine OneToOne 自引用双向关联不起作用?
用于 ManyToMany 的 Symfony Doctrine 重命名表
Symfony2-Doctrine:ManyToMany 关系未保存到数据库
php Doctrine Tabel Realtion Annotations(ManyToOne,OneToMany,ManyToMany)