簡體   English   中英

Symfony 3:表單中的allow_delete不起作用

[英]Symfony 3: allow_delete in Forms not working

我在Symfony 3中的表單有問題。我有一對多的聯接 (第2原理)。 它處理Orders( 訂單 ),Products( 產品 )和聯接實體( OrderProduct ),后者保存訂單中的產品數量。

我有一個用於添加和更新訂單條目的表單 ,該表單使用OrderProducts的Collection 所有這些都基於文檔( link )。

在表單中,我有一個用於添加產品按鈕 (從文檔中,向DOM添加<li>),每個添加的按鈕都有一個用於將其刪除按鈕 (從文檔中,從DOM中刪除<li>)。 這部分正在工作-添加和刪除DOM。

添加產品有效(與新訂單相比,在編輯時)。

但是我的問題是刪除。 從表單成功刪除的產品仍顯示$ editForm-> getData()中

訂購產品表格

namespace AppBundle\Form;

use AppBundle\Entity\ProductType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class OrderProductType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('amount')
            ->add('product')
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(
            array(
                'data_class' => 'AppBundle\Entity\OrderProduct',
            )
        );
    }

    public function getName()
    {
        return 'app_bundle_order_product_type';
    }
}

訂單

namespace AppBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class OrderType extends AbstractType
{

    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('customer')
            ->add('date', null, array('widget' => 'single_text'))
            ->add('payment', null, array('widget' => 'single_text'))
            ->add('processed', null, array('widget' => 'single_text'))
            ->add(
                'orderProducts',
                CollectionType::class,
                array(
                    'entry_type'    => OrderProductType::class,
                    'allow_add'     => true,
                    'allow_delete'  => true,
                    'by_reference'  => false,
                    'prototype'     => true,
                    'delete_empty'  => true,
                    'entry_options' => array('data_class' => 'AppBundle\Entity\OrderProduct'),
                )
            );

    }

    public function configureOptions(OptionsResolver $resolver)
    {
    }

    public function getName()
    {
        return 'app_bundle_order_type';
    }

}

OrderController中的當前操作 (添加產品有效,不能移除)公共功能editAction(請求$ request,$ orderId){

    $em = $this->getDoctrine()->getManager();
    $order = $em->getRepository('AppBundle:Order')->find($orderId);

    if (!$order) {
        throw $this->createNotFoundException('No order found for id '.$orderId);
    }

    $editForm = $this->createForm(OrderType::class, $order);
    $editForm->add('submit', SubmitType::class);

    $editForm->handleRequest($request);

    if ($editForm->isSubmitted() && $editForm->isValid()) {

        $order = $editForm->getData();

        //print '<pre>';
        //var_dump($order->getOrderProducts());
        //die();

        $orderProducts = $order->getOrderProducts();

        $em->persist($order);

        foreach ($orderProducts as $oneOrderProduct) {
            $oneOrderProduct->setOrder($order);
            $em->persist($oneOrderProduct);
        }

        //print '<pre>';
        //var_dump($order->getOrderProducts());
        //die();

        $em->flush();

        return $this->redirectToRoute('one_order', array('orderId' => $order->getId()));
    }


    return $this->render(
        'order/new.html.twig', array(
        'form' => $editForm->createView(),
    ));

}

我知道我必須在editAction中從Order中刪除已刪除的OrderProducts,但是現在不能了,因為從表單發送了所有OrderProducts。

訂單實體

namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\Common\Collections\ArrayCollection;
use AppBundle\Entity\OrderProduct;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;


/**
 * @ORM\Entity
 * @ORM\Table(name="order_")
 */
class Order
{

    /**
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
    /**
     * @ORM\ManyToOne(targetEntity="Customer", inversedBy="orders")
     * @ORM\JoinColumn(name="customer_id", referencedColumnName="id")
     */
    private $customer;
    /**
     * @ORM\Column(type="date")
     */
    private $date;
    /**
     * @ORM\Column(type="date")
     */
    private $payment;
    /**
     * @ORM\Column(type="date")
     */
    private $processed;

    public function __toString()
    {
        return strval($this->getId());
    }

    /**
     * @ORM\OneToMany(targetEntity="OrderProduct", mappedBy="order")
     */
    private $orderProducts;

    public function __construct()
    {
        $this->orderProducts = new \Doctrine\Common\Collections\ArrayCollection();
    }


    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set date
     *
     * @param \DateTime $date
     *
     * @return Order
     */
    public function setDate($date)
    {
        $this->date = $date;

        return $this;
    }

    /**
     * Get date
     *
     * @return \DateTime
     */
    public function getDate()
    {
        return $this->date;
    }

    /**
     * Set payment
     *
     * @param \DateTime $payment
     *
     * @return Order
     */
    public function setPayment($payment)
    {
        $this->payment = $payment;

        return $this;
    }

    /**
     * Get payment
     *
     * @return \DateTime
     */
    public function getPayment()
    {
        return $this->payment;
    }

    /**
     * Set processed
     *
     * @param \DateTime $processed
     *
     * @return Order
     */
    public function setProcessed($processed)
    {
        $this->processed = $processed;

        return $this;
    }

    /**
     * Get processed
     *
     * @return \DateTime
     */
    public function getProcessed()
    {
        return $this->processed;
    }

    /**
     * Set customer
     *
     * @param \AppBundle\Entity\Customer $customer
     *
     * @return Order
     */
    public function setCustomer(\AppBundle\Entity\Customer $customer = null)
    {
        $this->customer = $customer;

        return $this;
    }

    /**
     * Get customer
     *
     * @return \AppBundle\Entity\Customer
     */
    public function getCustomer()
    {
        return $this->customer;
    }

    /**
     * Add orderProduct
     *
     * @param \AppBundle\Entity\OrderProduct $orderProduct
     *
     * @return Order
     */
    public function addOrderProduct(\AppBundle\Entity\OrderProduct $orderProduct)
    {
        $this->orderProducts[] = $orderProduct;

        return $this;
    }

    /**
     * Remove orderProduct
     *
     * @param \AppBundle\Entity\OrderProduct $orderProduct
     */
    public function removeOrderProduct(\AppBundle\Entity\OrderProduct $orderProduct)
    {
        $this->orderProducts->removeElement($orderProduct);
    }

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

但是在POST中就可以了如您在此處看到的 ,這里我刪除了4個產品中的2個。 問題出現在表單處理中。

如果by_reference設置為false,則基礎Order實體在您的情況下必須具有一個名為[removeOrderProduct]的方法。 可能還有問題是您未在configureOptions方法內指定data_class選項。 在您的情況下,如果Order實體位於“ AppBundle \\ Entity \\ Order”中,則configureOptions方法應包含:

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'AppBundle\Entity\Order',
    ));
}

我建議您在OrderProductType類中也執行相同的操作。 我的猜測是,由於您尚未在OrderType類中指定'data_class'選項,因此'orderProducts'字段中的by_reference選項可能無法找出在哪里尋找[removeOrderProduct]方法。 因此,請設置該選項,並確保在Order實體類中具有該方法。

如果這不是問題,則應提供有關訂單實體以及在何處調用getData方法的更多信息。

更新:

查看您的代碼,我無法確定問題所在,這可能是導致實體無法移除的原因。 但是我在您的代碼中發現了一些奇怪之處:

在控制器中,在處理表單提交時,無需調用getData方法:調用handleRequest之后,$ order對象將更新並保存新信息(由於對象是通過引用傳遞的,因此,在沒有表單的情況下,表單無法應用更改同時更改原始的$ order)。 因此,不需要$ order = $ form-> getData(),因為您之前已經定義了$ order變量,並且該變量保存對表單映射已發布值的同一對象的引用。

如果那沒有幫助,我建議您添加死點。 語句遍布各處,只是為了確保在每一步都調用正確的方法。 例如添加模具; 到removeOrderProduct方法,以檢查其是否命中。 如果遇到問題,從您提供給我們的數據中不會發現問題,因此需要進一步調試。

現在也可能不是問題,但是如果要在提交后刪除列表中不存在的產品,則必須調用$ order-> getOrderProducts並將每個項目添加到保存先前orderProducts的新集合中(提交前),並將其與提交后的值進行比較,以找出需要刪除的值。

我昨晚解決了:)

這是正在工作的控制器動作:

/**
 * @Route("/{orderId}/edit", name="edit_order", requirements={"orderId": "\d+"})
 * @param Request $request
 * @param         $orderId
 *
 * @return \Symfony\Component\HttpFoundation\RedirectResponse|\Symfony\Component\HttpFoundation\Response
 */
public function editAction(Request $request, $orderId)
{
    $em = $this->getDoctrine()->getManager();
    $order = $em->getRepository('AppBundle:Order')->find($orderId);

    if (!$order) {
        return $this->redirectToRoute('new_order');
    }

    $originalOrderProducts = new ArrayCollection();

    foreach ($order->getOrderProducts() as $orderProduct) {
        $originalOrderProducts->add($orderProduct);
    }

    $editForm = $this->createForm(OrderType::class, $order);
    $editForm->add('submit', SubmitType::class);
    $editForm->handleRequest($request);

    if ($editForm->isSubmitted() && $editForm->isValid()) {

        $orderProducts = $order->getOrderProducts();

        foreach ($originalOrderProducts as $oneOriginalOrderProduct) {
            if (false === $order->getOrderProducts()->contains($oneOriginalOrderProduct)) {
                $order->removeOrderProduct($oneOriginalOrderProduct);
                $em->remove($oneOriginalOrderProduct);
                $em->flush();
            }
        }

        foreach ($orderProducts as $oneOrderProduct) {
            if ($oneOrderProduct->getAmount() == 0) {
                $order->removeOrderProduct($oneOrderProduct);
                $em->remove($oneOrderProduct);
            } else {
                if (!$originalOrderProducts->contains($oneOrderProduct)) {
                    $oneOrderProduct->setOrder($order);
                }
                $em->persist($oneOrderProduct);
            }
            $em->persist($order);
            $em->flush();
        }

        return $this->redirectToRoute('order');
    }

    return $this->render('order/new.html.twig', array('form' => $editForm->createView()));

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM