[英]Symfony2 Form Collection allow_add and allow_delete null error (Silex)
[英]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;
}
}
如果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.