Doctrine ManyToMany自引用bidirectionnal - 父级未更新

时间:2018-03-27 13:07:38

标签: symfony doctrine many-to-many relational-database

我试图创建一个公司的ManyToMany关系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(),
    ));
}

生成的表单如下所示:

ServiceType generated

问题:

我的问题是孩子的更新但父母不是。我可以在$service变量中看到父项dump()在我的控制器中,但在我的数据库表(app_services_hierarchie)中更新的只有孩子。

1 个答案:

答案 0 :(得分:1)

代码中$parents$enfants之间的区别在于,您$enfants映射时,您正在查看的服务是拥有方,但不是$parents映射的情况。

除非您通过$parents告知cascade={"persist"},否则该原则不会存储/** * @ORM\ManyToMany(targetEntity="AppBundle\Entity\Service", mappedBy="enfants", cascade={"persist"}) */

$parents

这与@GregoireDucharme关联的帖子中给出的答案基本相同。

编辑:经过一番研究,显然这个问题无法用级联来解决。根据{{​​3}}:

  

Doctrine只会检查协会的拥有方是否有变更。

所以你要做的就是告诉你的$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,则不会调用removeParentcascade

Anny Filina对此Doctrine documentation表示赞同。

它还声明您可以从$parents媒体资源中删除cascade={"persist","remove"}选项,但您可能应该将$enfants添加到{{1}}媒体资源中。