我正在为symfony的演出创建一个票证预订表单。
每个演出都有多个演出数据。在db中,performanceData记录包含诸如日期,位置和可用票证类型列表之类的内容。每个performanceData记录的可用故障单类型可能不同。
当用户想要预订时,他必须选择性能数据。 根据此选择,他应该获得一个列表,其中包含所有可用的票证类型+每个票证类型a(数字)字段以选择票证数量。这就是我被困的地方。
我使用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
*
* @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 :(得分:1)
如果要使用动态表单,则应使用JavaScript。 如您所知,Symfony是一个在服务器端工作的PHP框架。 您可以从控制器一次创建表单。事件在提交之前或提交之后调用...而不是在客户端操作期间。 要执行您想要的操作,您必须使用js获取性能数据值并将其发送(Ajax调用)到控制器,它将根据性能数据返回可用的票证。 并使用javascript
在表单中显示可用的票证答案 1 :(得分:0)
我认为问题在于预留应该与PerformanceData和TicketType(两者)相关联,因此您的实体预留应该具有这两个具有关联的字段。
然后你应该使用EntityType,并使用你的实体作为类。 Symfony应自动制作选择列表:
$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个。您现在可以隐藏其中一个,如果有人从第一个选择列表中选择一些值,您可以显示带有过滤值的第二个列表。
恕我直言,这应该有所帮助。