从Symfony / Doctrine One中的表单集合中删除记录 - >多个关系

时间:2018-01-25 19:55:18

标签: symfony doctrine-orm formcollection

尝试从嵌入在另一个表单中的表单集合中删除实体记录。我已经成功地将实体记录添加到同一个表单集合中。

表单集合实体(quoteItemDeliverable)与父实体(quoteItem)处于1对多的关系中。

使用symfony 3.3 / Doctrine并使用相应的文档https://symfony.com/doc/3.3/form/form_collections.html

使用文档我可以删除表单元素,表单元素是表单(twig)中存在的集合中的项目。下面控制器代码中的dump()将显示在编辑表单中从集合中删除的项目。但是当$ quoteItem被持久化时,表单中已删除的集合项不会从实体中的集合中删除(记录未被删除)。

我们正在使用的控制器代码

    /**
 * Edit an existing ring quote entity.
 *
 * @Route("/{id}/edit", name="quote-ring_edit")
 * @Method({"GET", "POST"})
 */
public function editAction (Request $request, QuoteItem $quoteItem)
{
    $type = $quoteItem->getCategory();

    $form = $this->createForm('UniflyteBundle\Form\QuoteItemType', $quoteItem, ['allow_extra_fields' => true, 'attr' => ['quote-type' => 2, 'category-type' => $type]]);
    $form->add('QuoteRing', QuoteRingType::class, ['label' => false]);

    $form->handleRequest($request);
    if ($form->isSubmitted() && $form->isValid()) {
        dump($quoteItem);
        $em = $this->getDoctrine()->getManager();

        $em->persist($quoteItem);
        $em->flush();

        //return $this->redirectToRoute('quote-ring_edit', ['id' => $quoteItem->getId()]);
    }

    return $this->render("quoteitem/ring.html.twig", [
        'quoteItem' => $quoteItem,
        'form_new'  => false,
        'type'      => $type,
        'form'      => $form->createView()
    ]);
}

该集合的表单类型如

          ->add('quoteItemDeliverables', CollectionType::class, [
        'entry_type'    => QuoteItemDeliverableType::class,
        'entry_options' => array ('label' => false),
        'by_reference'  => false,
        'allow_add'     => true,
        'allow_delete'  => true,
        'prototype'     => true,
      ])

用于形成集合注释的quoteItem实体。

/**
 * @ORM\OneToMany(
 *     targetEntity="UniflyteBundle\Entity\QuoteItemDeliverable",
 *     mappedBy="quoteItem",
 *     cascade={"persist","detach","remove"}
 * )
 */
private $quoteItemDeliverables;

quoteItem类中用于添加和删除集合中项目的方法

/**
 * Add quoteItemDeliverable
 *
 * @param \UniflyteBundle\Entity\QuoteItemDeliverable $quoteItemDeliverable
 *
 * @return QuoteItem
 */
public function addQuoteItemDeliverable (\UniflyteBundle\Entity\QuoteItemDeliverable $quoteItemDeliverable)
{
    $quoteItemDeliverable->setQuoteItem($this);
    $this->quoteItemDeliverables[] = $quoteItemDeliverable;

    return $this;
}

/**
 * Remove quoteItemDeliverable
 *
 * @param \UniflyteBundle\Entity\QuoteItemDeliverable $quoteItemDeliverable
 */
public function removeQuoteItemDeliverable (\UniflyteBundle\Entity\QuoteItemDeliverable $quoteItemDeliverable)
{
    $this->quoteItemDeliverables->removeElement($quoteItemDeliverable);
}

/**
 * Get quoteItemDeliverables
 *
 * @return \Doctrine\Common\Collections\Collection
 */
public function getQuoteItemDeliverables ()
{
    return $this->quoteItemDeliverables;
}

文档指出,对于一对多,我们可能必须明确删除关系(上面提供的文档链接中的snipplet)。我不明白为什么。

foreach ($originalTags as $tag) {
        if (false === $task->getTags()->contains($tag)) {
            // remove the Task from the Tag
            $tag->getTasks()->removeElement($task);

            // if it was a many-to-one relationship, remove the relationship like this
            // $tag->setTask(null);

            $em->persist($tag);

            // if you wanted to delete the Tag entirely, you can also do that
            // $em->remove($tag);
        }

有没有人知道我在控制器上做错了什么转储正确反映但是持久性删除记录的操作没有发生?

提前感谢您花时间和精力来应对这一挑战。

更新 - :我关注了DonCallisto' s建议并成功地从实体级别的集合中删除项目,控制器中包含以下内容

if ($form->isSubmitted() && $form->isValid()) {
        $em = $this->getDoctrine()->getManager();

        // NOTE: Remove the quote item deliverables - will need for additional work as well?
        foreach ($em->getRepository('UniflyteBundle:QuoteItemDeliverable')->findAll() as $quoteItemDeliverable) {
            if (false === $quoteItem->getQuoteItemDeliverables()->contains($quoteItemDeliverable)) {
                $em->remove($quoteItemDeliverable);
                $em->persist($quoteItem);
            }
        }
        $em->flush();

        return $this->redirectToRoute('blah', ['id' => $quoteItem->getId()]);
    }

1 个答案:

答案 0 :(得分:2)

那是因为你要从关系的inversed side中删除它。 Doctrine can actually check only for changes in owning side,所以就像你没有删除它一样,因为拥有方没有改变。

您需要通过EntityManager以编程方式删除该项目,或在注释中将orphanRemoval设置为true(但我不会推荐它!)。 我不建议使用orphanRemoval,因为即使它使您无法编写更多代码,也无法将删除的元素重新分配给其他集合(只是为了让您免受未来的麻烦)

此外,请务必在from at collection字段中添加by_reference => false,否则将不会调用add*remove*方法。