2016-08-18 291 views
0

我有一個建立在購買想法上的表單。它有購買物品,付款金額和付款方式(VISA,萬事達卡,現金)。我已經預先填寫了2個購買物品的表單,但是如果用戶選擇卡支付類型(VISA或萬事達卡)類型,我正在嘗試添加其他購買物品。 這個額外的購買項目,我想通過控制器添加。在頁面提交後向Symfony2表單集合類型添加其他項目

Rendered Form view

真正的問題是,我在哪裏實現控制器動作這個功能......或者是更好,因爲在表單類型的事件監聽?

當形式與附加卡工本費購買項目我碰到下面的錯誤...

Catchable Fatal Error: Argument 1 passed to Aazp\BookingBundle\Entity\PurchaseItem::__construct() must be an instance of Aazp\BookingBundle\Entity\Product, none given, called in /project/vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/Type/FormType.php on line 141 and defined in /project/src/Aazp/BookingBundle/Entity/PurchaseItem.php line 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

沒有看到PurchaseItem.php? – Fiemhong

回答

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

+0

甚至沒有看這許多謝謝Yonel。 我認爲異常指的是Purchase Item代理實體或在表單初始預加載後創建的新實體。根據例外情況,我認爲他們沒有關聯的產品。 因此,這固定了我的問題的第一部分,現在我已經設法修復其餘部分。現在我希望這只是簡單的邏輯來實現,然後完成。 再次感謝Yonel,你讓我再次前進。 (y)的 – tmschneider