我有一个案例,我们为体育赛事创建注册。
注册包含特定于每项运动的一些字段。其中一些将以相似的名称命名,尽管它们对于每项运动都会有所不同。示例:“场上最喜欢的位置”:
对于篮球来说,它将是一个选择领域:
对于棒球,它将是相同的选择领域,但有一些不同的选择:
首次创建表单(用于显示)时,该项运动将作为注册数据的一部分传递:
$registration = new Registration;
$registration->setEvent($event);
和$event->getSport();
将为该活动返回该项运动。
到目前为止一直很好,并且在我的表单生成中添加了一个监听器,我只能设置特定于该运动的字段:
public static function getSubscribedEvents()
{
return [FormEvents::POST_SET_DATA => 'preSetData'];
}
/**
* @param event DataEvent
*/
public function preSetData(DataEvent $event)
{
$form = $event->getForm();
if (null === $event->getData()) {
return;
}
// (The get event here means the real life sports gathering)
$sport = $event->getData()->getEvent()->getSport();
/**
* Then I customize the fields depending on the current sport
*/
}
当用户提交此表单时,问题就出现了。在这种情况下,$event->getData()->getEvent()
为null
。
“事件”(现实生活中的一个)是注册表单中的document_id
字段(在此处使用MongoDB)。
如果我收听::BIND
事件而不是::PRE_SET_DATA
,那么我可以访问所有内容,但是因为它已经绑定而定制表单已经太晚了。 ::PRE_BIND
与::PRE_SET_DATA
的作用相同。
如何在此处正确检索我的活动和体育文档,以便自定义我的表单并进行相应的验证?
答案 0 :(得分:0)
为什么你需要一个事件来完成这样的任务?您可以在表单类的buildForm()
操作中定义字段。要访问事件对象,只需使用$options['data']->getEvent()
答案 1 :(得分:0)
所以...终于找到了如何正确地做到这一点。它需要订阅两个不同的事件。
第一次构建表单时,会将一些数据传递给它,因此,PRE_SET_DATA
事件包含该数据,一切正常,如问题中所述。
在提交表单时,首先使用NO数据创建表单,因此PRE_SET_DATA
中访问的数据将为null。在这种情况下,我们跳过表单自定义:
public function preSetData(DataEvent $event)
{
$myEvent = $event->getData()->getEvent();
if (null === $myEvent) {
return;
}
$this->customizeForm();
}
这确保我们在提交表单时不会遇到问题并且没有传递数据,但是getData()
将返回一个空对象而不是NULL。
现在,提交表单时,我们会将其绑定到收到的数据。那是我们想要干涉的时候。所以我们还会订阅PRE_BIND
事件:
public static function getSubscribedEvents()
{
return [
FormEvents::PRE_BIND => 'preBind',
FormEvents::PRE_SET_DATA => 'preSetData',
];
}
在预绑定中,我们收到的数据只是一个值数组而不是对象图。 但是如果我们在侦听器中注入了对象管理器,那么我们就可以找到我们的对象并使用它们:
public function preBind(DataEvent $event)
{
$data = $event->getData();
$id = $data['event'];
$myEvent = $this->om
->getRepository('Acme\DemoBundle\Document\Event')
->find(new \MongoId($id));
if($myEvent === null){
$msg = 'The event %s could not be found';
throw new \Exception(sprintf($msg, $id));
}
$this->customizeForm();
}