我有一个基于购买理念的表格。它有购买物品,付款金额和付款方式(VISA,万事达卡,现金)。我预先加载了2个购买物品,但是如果用户选择卡片付款类型(VISA或万事达卡)类型,我会尝试添加额外的购买物品。 这个额外的购买物品我试图通过控制器添加。
问题是,我在哪里可以在Controller Action中实现这个功能......或者它作为Form Type上的EventListener更好吗?
当表单与附加的卡费购买项目一起提交时,我收到以下错误...
捕获致命错误:传递给Aazp \ BookingBundle \ Entity \ PurchaseItem :: __ construct()的参数1必须是Aazp \ BookingBundle \ Entity \ Product的实例,没有给出,在/ project / vendor / symfony / symfony /中调用第141行的src / Symfony / Component / Form / Extension / Core / Type / FormType.php,在/project/src/Aazp/BookingBundle/Entity/PurchaseItem.php第20行中定义
BookingController
namespace Aazp\BookingBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Aazp\BookingBundle\Entity\Booking;
use Aazp\BookingBundle\Entity\Passenger;
use Aazp\BookingBundle\Entity\Payment;
use Aazp\BookingBundle\Entity\Purchase;
use Aazp\BookingBundle\Entity\PurchaseItem;
use Aazp\BookingBundle\Form\PurchaseItemType;
use Aazp\BookingBundle\Form\PurchaseType;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class BookingController extends Controller
{
public function passengerPaymentAction($passenger_id)
{
$request = Request::createFromGlobals();
$purchaseBalance = 0.0;
//Query the selected Passenger
$em = $this->getDoctrine()->getManager();
$passenger = $request->attributes->get('passenger', $em->getRepository('AazpBookingBundle:Passenger')->find($passenger_id));
if (!$passenger) {
throw $this->createNotFoundException('Unable to find Passenger entity.');
}
$purchase = $passenger->getPurchase();
//Has this Passenger made a Payment. If yes then Purchase exists.
if($purchase === NULL) //If Purchase does not exist then preload the form with default products.
{
$purchase = new Purchase();
$product_category_photo = $em->getRepository('AazpBookingBundle:ProductCategory')->findOneByName('FLIGHT-PHOTO');
$product_photo_option = $em->getRepository('AazpBookingBundle:Product')->findOneByProductCategory($product_category_photo);
if (!$product_photo_option) {
throw $this->createNotFoundException('Unable to find Flight Photo Product entity.');
}
$purchase_item_flight = new PurchaseItem($passenger->getFlight());
$purchase_item_photo_option = new PurchaseItem($product_photo_option);
//Add Purchase Items to the Purchase
$purchase->addPurchaseItem($purchase_item_flight);
$purchase->addPurchaseItem($purchase_item_photo_option);
//Set the Purchase on the Passenger
$passenger->setPurchase($purchase);
}
//Ajax call triggered by onChange event on PaymentType radio button in form
//Add additional Purchase Item for Card Type Payment
if($form->get('paymentType')->getData()->getId() > 1)
{
//PaymentType selected/modified then calculate Payment Fee
$product_category_card_fee = $em->getRepository('AazpBookingBundle:ProductCategory')->findOneByName('CARD-FEE');
$product_card_fee = $em->getRepository('AazpBookingBundle:Product')->findOneByProductCategory($product_category_card_fee);
if (!$productcard_fee) {
throw $this->createNotFoundException('Unable to find Card Fee Product entity.');
}
$purchase_item_card_fee = new PurchaseItem($product_card_fee);
//Add Purchase Items to the Purchase
$purchase->addPurchaseItem($purchase_item_card_fee);
$passenger->setPurchase($purchase);
return $this->render('AazpBookingBundle:Purchase:summary.html.twig', array(
'passenger' => $passenger,
'form' => $form->createView(),
));
}
$form = $this->createForm(new PurchaseType($em), $purchase);
$form->handleRequest($request);
//If form is Valid create Payment and persist.
if ($form->isValid())
{
$payment = new Payment();
$payment->setAmount($form->get('paymentAmount')->getData());
$payment->setPaymentType($form->get('paymentType')->getData());
$payment->setDescription($form->get('description')->getData());
$passenger->getPurchase()->addPayment($payment);
$passenger->getBooking()->setStatus(Booking::STATUS_CONFIRMED);
$em->persist($passenger->getPurchase());
$em->flush();
$this->get('session')->getFlashBag()->add('message', 'Payment '.$payment->getAmount().' CHF has been successful!');
return $this->redirect($this->generateUrl('booking_show', array ('id'=> $passenger->getBooking()->getId())));
}
return $this->render('AazpBookingBundle:Purchase:summary.html.twig', array(
'passenger' => $passenger,
'form' => $form->createView(),
));
}
}
PurchaseItemType
namespace Aazp\BookingBundle\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Aazp\BookingBundle\Entity\ProductRepository;
class PurchaseItemType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('product', 'entity', array('label' => 'Flight', 'class' => 'AazpBookingBundle:Product','property' => 'name', 'empty_value' => 'Please Select', 'required' => false, ));
$builder->add('amount', 'number', array('precision' => 2));
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array('data_class' => 'Aazp\BookingBundle\Entity\PurchaseItem', ));
}
public function getName()
{
return 'purchaseItem';
}
}
PurchaseType
namespace Aazp\BookingBundle\Form;
use Doctrine\ORM\EntityManager;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
use Aazp\BookingBundle\Entity\PurchaseItem;
class PurchaseType extends AbstractType
{
protected $em;
function __construct(EntityManager $em)
{
$this->em = $em;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('purchaseItems', 'collection', array('type' => new PurchaseItemType(), 'allow_add' => true, 'allow_delete' => true, 'by_reference' => false));
$builder->add('paymentType', 'entity', array('label' => 'Payment Type', 'class' => 'AazpBookingBundle:PaymentType','property' => 'name', 'mapped' => false, 'expanded' => true));
$builder->add('paymentAmount', 'number', array('precision' => 2, 'data' => 0.0, 'mapped' => false));
$builder->add('description', 'text', array('mapped' => false, 'required' => false));
$builder->add('cancel', 'submit', array('attr' => array('formnovalidate' => true, 'data-toggle' => 'modal', 'data-target' => '#cancelWarning', )));
$builder->add('pay', 'submit');
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array('data_class' => 'Aazp\BookingBundle\Entity\Purchase', ));
}
public function getName()
{
return 'purchase';
}
}
购买实体
<?php
namespace Aazp\BookingBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Mapping\Annotation as Gedmo;
use Symfony\Component\Validator\Constraints as Assert;
use Aazp\MainBundle\Entity\BaseEntity;
/**
* @ORM\Entity(repositoryClass="Aazp\BookingBundle\Entity\PurchaseRepository")
* @ORM\Table(name="purchase")
* @Gedmo\SoftDeleteable(fieldName="deleted")
*/
class Purchase extends BaseEntity
{
/**
* Constructor
*/
public function __construct()
{
$this->purchaseItems = new \Doctrine\Common\Collections\ArrayCollection();
$this->payments = new \Doctrine\Common\Collections\ArrayCollection();
}
/**
* @ORM\Column(type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\ManyToMany(targetEntity="PurchaseItem", cascade={"all"})
* @ORM\JoinTable(name="purchase_purchase_items",
* joinColumns={@ORM\JoinColumn(name="purchase_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="purchase_item_id", referencedColumnName="id", unique=true)}
* )
**/
protected $purchaseItems;
/**
* @ORM\ManyToMany(targetEntity="Payment", inversedBy="purchases", cascade={"all"})
* @ORM\JoinTable(name="purchases_payments",
* joinColumns={@ORM\JoinColumn(name="purchase_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="payment_id", referencedColumnName="id")}
* )
**/
protected $payments;
/**
* @ORM\OneToOne(targetEntity="Passenger", mappedBy="purchase")
**/
protected $passenger;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Add purchaseItems
*
* @param \Aazp\BookingBundle\Entity\PurchaseItem $purchaseItems
* @return Purchase
*/
public function addPurchaseItem(\Aazp\BookingBundle\Entity\PurchaseItem $purchaseItems)
{
$this->purchaseItems[] = $purchaseItems;
return $this;
}
/**
* Remove purchaseItems
*
* @param \Aazp\BookingBundle\Entity\PurchaseItem $purchaseItems
*/
public function removePurchaseItem(\Aazp\BookingBundle\Entity\PurchaseItem $purchaseItems)
{
$this->purchaseItems->removeElement($purchaseItems);
}
/**
* Get purchaseItems
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getPurchaseItems()
{
return $this->purchaseItems;
}
/**
* Add payments
*
* @param \Aazp\BookingBundle\Entity\Payment $payments
* @return Purchase
*/
public function addPayment(\Aazp\BookingBundle\Entity\Payment $payments)
{
$this->payments[] = $payments;
return $this;
}
/**
* Remove payments
*
* @param \Aazp\BookingBundle\Entity\Payment $payments
*/
public function removePayment(\Aazp\BookingBundle\Entity\Payment $payments)
{
$this->payments->removeElement($payments);
}
/**
* Get payments
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getPayments()
{
return $this->payments;
}
/**
* Set passenger
*
* @param \Aazp\BookingBundle\Entity\Passenger $passenger
* @return Purchase
*/
public function setPassenger(\Aazp\BookingBundle\Entity\Passenger $passenger = null)
{
$this->passenger = $passenger;
return $this;
}
/**
* Get passenger
*
* @return \Aazp\BookingBundle\Entity\Passenger
*/
public function getPassenger()
{
return $this->passenger;
}
}
答案 0 :(得分:0)
这是因为默认的data_class
选项调用没有参数的构造函数。如果您的类Aazp\Booking Bundle\Entity\PurchaseItem
在构造函数中包含参数,则需要使用empty_data
选项来实例化:
// Aazp\BookingBundle\Form\PurchaseItemType.php
$resolver->setDefaults([
'empty_data' => function (FormInterface $form) {
return new PurchaseItem($form->get('product')->getData());
},
]);
您可以更多地了解此选项here。