2017-09-17 17 views
0

私はsymfonyで公演のチケット予約のためのフォームを作成しています。Symfonyの選択に基づいてカスタムタイプを動的に追加するには?

すべてのパフォーマンスには複数のパフォーマンスデータがあります。 dbでは、performanceDataレコードには日付、場所、利用可能なチケットの種類などの情報が含まれています。利用可能なチケットの種類は、performanceDataレコードごとに異なる場合があります。

ユーザが予約をしたいとき、彼はパフォーマンスデータを選択しなければならない。 この選択に基づいて、利用可能なすべてのチケットタイプ+チケットタイプごとのリストを取得して、チケット数を選択する必要があります。これは私が立ち往生している場所です。

symfonyのドキュメントを使用して、使用可能なチケットタイプをドロップダウンにロードするための動的フォームをユーザの選択に基づいて使用しました。しかし、どのように利用可能なチケットタイプ+番号フィールドを持つリストを追加するのですか?このリストは、予約エンティティの「チケット」とマッピングする必要があります。

マイエンティティ:

PerformanceData

/** 
* PerformanceData 
* 
* @ORM\Table(name="performance_data") 
* @ORM\Entity 
*/ 
class PerformanceData 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var \DateTime 
    * 
    * @ORM\Column(name="date", type="datetime", nullable=false) 
    */ 
    private $date; 

    /** 
    * @var Performance 
    * 
    * @ORM\ManyToOne(targetEntity="Performance", inversedBy="performanceData") 
    */ 
    private $performance; 

    /** 
    * @var \AppBundle\Entity\Location 
    * 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Location") 
    * @ORM\JoinColumn(name="location_id", referencedColumnName="id") 
    */ 
    private $location; 

    /** 
    * @var ArrayCollection 
    * 
    * @ORM\ManyToMany(targetEntity="AppBundle\Entity\TicketType") 
    * @ORM\JoinTable(name="performance_data_ticket_type", 
    * joinColumns={ 
    *  @ORM\JoinColumn(name="performance_data_id", referencedColumnName="id") 
    * }, 
    * inverseJoinColumns={ 
    *  @ORM\JoinColumn(name="ticket_type_id", referencedColumnName="id") 
    * } 
    *) 
    */ 
    private $availableTicketTypes; 

    //getters/setters... 

    /** 
    * @return string 
    */ 
    public function getDisplayText() 
    { 
     return $this->getPerformance()->getInfoTitle() . ' - ' . strftime('%A %d %B %Y', $this->getDate()->getTimestamp()); 
    } 
} 

予約

/** 
* Reservation 
* 
* @ORM\Table(name="reservation") 
* @ORM\Entity 
*/ 
class Reservation 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var PerformanceData 
    * 
    * @ORM\ManyToOne(targetEntity="PerformanceData") 
    * @ORM\JoinColumn(name="performance_data_id", referencedColumnName="id") 
    */ 
    private $performanceData; 

    /** 
    * @var ArrayCollection 
    * 
    * @ORM\OneToMany(targetEntity="AppBundle\Entity\ReservationTicket", mappedBy="reservation") 
    */ 
    private $tickets; 

    //getters/setters... 
} 

ReservationTicket

/** 
* ReservationTicket 
* 
* @ORM\Table(name="reservation_ticket") 
* @ORM\Entity 
*/ 
class ReservationTicket 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="amount", type="smallint", nullable=false) 
    */ 
    private $numberOfTickets; 

    /** 
    * @var Reservation 
    * 
    * @ORM\ManyToOne(targetEntity="Reservation", inversedBy="tickets") 
    * @ORM\JoinColumn(name="reservation_id", referencedColumnName="id") 
    */ 
    private $reservation; 

    /** 
    * @var \AppBundle\Entity\TicketType 
    * 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\TicketType") 
    * @ORM\JoinColumn(name="ticket_type_id", referencedColumnName="id") 
    */ 
    private $ticketType; 

    //getters/setters... 
} 

私の予約タイプのフォーム

/** 
* Class ReservationType 
* @package AppBundle\Form 
*/ 
class ReservationType extends AbstractType 
{ 
    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 


     $builder->add('performanceData', EntityType::class, 
       array(
        'label'   => 'Voorstelling', 
        'class'   => 'AppBundle:PerformanceData', 
        'query_builder' => function (EntityRepository $er) { 
         return $this->getOpenReservations($er); 
        }, 
        'group_by'  => function ($performanceData) { 
         if ($performanceData instanceof PerformanceData && 
          $performanceData->getPerformance() instanceof Performance 
         ) { 
          return $performanceData->getPerformance()->getInfoTitle(); 
         } 

         return 'Andere voorstellingen'; 
        }, 
        'choice_label' => 'displayText', 
        'required'  => true, 
       ) 
      ); 

     //event listener for ticket types 
     $formModifier = function (FormInterface $form, PerformanceData $performanceData = null) { 
      $availableTicketTypes = array(); 
      $reservationTickets = array(); 

      if ($performanceData instanceof PerformanceData) { 
       $availableTicketTypes = $performanceData->getAvailableTicketTypes(); 
      } 

      foreach ($availableTicketTypes as $availableTicketType) { 
       $reservationTickets[] = $availableTicketType->getDisplayText(); 

       $form->add('tickets', ChoiceType::class, array(
        'label' => 'tickets', 
        'choices' => $reservationTickets, 
        'mapped' => false 
       )); 
      } 
     }; 

     $builder->addEventListener(
      FormEvents::PRE_SET_DATA, 
      function (FormEvent $event) use ($formModifier) { 
       // this would be your entity, i.e. SportMeetup 
       $data = $event->getData(); 

       $formModifier($event->getForm(), $data->getPerformanceData(), $data); 
      } 
     ); 

     $builder->get('performanceData')->addEventListener(
      FormEvents::POST_SUBMIT, 
      function (FormEvent $event) use ($formModifier) { 
       // It's important here to fetch $event->getForm()->getData(), as 
       // $event->getData() will get you the client data (that is, the ID) 
       $performanceData = $event->getForm()->getData(); 

       // since we've added the listener to the child, we'll have to pass on 
       // the parent to the callback functions! 
       $formModifier($event->getForm()->getParent(), $performanceData); 
      } 
     ); 
    } 

    /** 
    * @param OptionsResolver $resolver 
    */ 
    public function configureOptions(OptionsResolver $resolver) 
    { 
     $resolver->setDefaults(
      array(
       'data_class' => Reservation::class 
      ) 
     ); 
    } 
} 

ありがとう!

編集:

私の質問は少し曖昧でした。

  • ロード可能なチケットタイプごとに利用可能なすべてのチケットタイプ
  • :動的に追加する「番号」の入力フィールドを追加

    ユーザーがパフォーマンス・データを選択した場合:これは私が達成したいものですチケットの数。

  • 私はreservationTicketエンティティ持っ予約エンティティ

でチケットにこれらのフィールドをマップ:私は問題は予約がそう、PerformanceDataとTicketType(両方)に関連付けされなければならないということだと思います

/** 
* ReservationTicket 
* 
* @ORM\Table(name="reservation_ticket") 
* @ORM\Entity 
*/ 
class ReservationTicket 
{ 
    /** 
    * @var integer 
    * 
    * @ORM\Column(name="id", type="integer") 
    * @ORM\Id 
    * @ORM\GeneratedValue(strategy="AUTO") 
    */ 
    private $id; 

    /** 
    * @var integer 
    * 
    * @ORM\Column(name="amount", type="smallint", nullable=false) 
    */ 
    private $numberOfTickets; 

    /** 
    * @var Reservation 
    * 
    * @ORM\ManyToOne(targetEntity="Reservation", inversedBy="tickets") 
    * @ORM\JoinColumn(name="reservation_id", referencedColumnName="id") 
    */ 
    private $reservation; 

    /** 
    * @var \AppBundle\Entity\TicketType 
    * 
    * @ORM\ManyToOne(targetEntity="AppBundle\Entity\TicketType") 
    * @ORM\JoinColumn(name="ticket_type_id", referencedColumnName="id") 
    */ 
    private $ticketType; 

答えて

0

をあなたのエンティティ予約はこれらの2つのフィールドを関連付ける必要があります。

次に、EntityTypeを使用し、クラスとしてエンティティを使用する必要があります。 symfonyは自動的にチョイスリストを作成する必要があります:

http://symfony.com/doc/current/reference/forms/types/entity.html#using-a-custom-query-for-the-entities

$builder->add('users', EntityType::class, array(
    'class' => 'AppBundle:User', 
    'query_builder' => function (EntityRepository $er) { 
     return $er->createQueryBuilder('u') 
      ->orderBy('u.username', 'ASC'); 
    }, 
    'choice_label' => 'username', 
)); 

その後、フォームに2つの選択肢が必要です。それらのうちの1つを隠すことができるようになり、誰かが最初の選択リストから値を選択した場合、フィルタリングされた値で2番目のリストを表示することができます。

IMHOこれが役立ちます。

+0

こんにちは、お返事ありがとうございます!私の質問はやや曖昧だったと思うので、編集しました。 :) –

+0

ようこそ。私の答えが助けられたら、あなたはいつも投票することができます;) – Arkowsky

1

動的にフォームを使用する場合は、JavaScriptを使用する必要があります。 Symfonyは、サーバー側で動作するPHPフレームワークです。 コントローラから一度フォームを作成します。このイベントは、クライアントアクション中ではなく、送信前または送信後に呼び出されています。 パフォーマンスデータ値をjsで取得し、Ajax呼び出しをコントローラに送信して、パフォーマンスデータに基づいて利用可能なチケットを返す必要があるようにします。 JavaScriptでフォームにチケットを表示