Php 如何根据Symfony中的选择动态添加自定义类型?
我正在为在symfony演出的门票预订创建一个表单 每个性能都有多个性能数据。在数据库中,performanceData记录包含日期、位置和可用票证类型列表等内容。每个performanceData记录的可用票证类型可能不同 当用户想要预订时,他必须选择一个性能数据。 基于此选择,他应该获得一个包含所有可用票证类型的列表+每个票证类型a(编号)字段,以选择票证数量。这就是我被困的地方 我使用symfony文档创建了一个动态表单,根据用户的选择在下拉列表中加载可用的票证类型。但是如何添加带有可用票证类型+编号字段的列表?此列表应与预订实体中的“票证”对应 我的实体: 性能数据Php 如何根据Symfony中的选择动态添加自定义类型?,php,forms,symfony,Php,Forms,Symfony,我正在为在symfony演出的门票预订创建一个表单 每个性能都有多个性能数据。在数据库中,performanceData记录包含日期、位置和可用票证类型列表等内容。每个performanceData记录的可用票证类型可能不同 当用户想要预订时,他必须选择一个性能数据。 基于此选择,他应该获得一个包含所有可用票证类型的列表+每个票证类型a(编号)字段,以选择票证数量。这就是我被困的地方 我使用symfony文档创建了一个动态表单,根据用户的选择在下拉列表中加载可用的票证类型。但是如何添加带有可用票
/**
* 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
*
* @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;
我认为问题在于预订应该与PerformanceData和TicketType(两者)相关联,因此您的实体预订应该具有这两个关联字段 然后您应该使用EntityType,并作为类使用您的实体。Symfony应自动生成选项列表: e、 g 之后,你的表格上应该有2个选项。现在可以隐藏其中一个,如果有人从第一个选择列表中选择某个值,则可以显示第二个列表,其中包含过滤后的值
这应该会有帮助。如果您想动态使用表单,您应该使用JavaScript。 正如您所知,Symfony是一个在服务器端工作的PHP框架。 从控制器一次创建一个表单。事件正在提交前或提交后调用。。。不是在客户端操作期间。 要做您想要做的事情,您必须使用js获取性能数据值,并将其发送(Ajax调用)给控制器,控制器将根据性能数据返回可用的票证。
您可以使用javascript在表单中显示可用的票证Hi,感谢您的回答!我认为我的问题有点含糊(我的错误),所以我对它进行了编辑不客气。如果我的回答有帮助,你总是可以投赞成票;)当做
$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',
));