2012-10-29 26 views
1

我有一个案例,我们为体育赛事创建注册。如何在检索时自定义symfony2表单?

注册包含一些特定于每项运动的字段。其中一些将被命名为相似,尽管它们对于每项运动都会有所不同。例如: “在球场上最喜欢的体位”:

篮球这将是之间的选择字段:

  • 控球后卫
  • 得分后卫
  • 等...

对于棒球,这将是相同的选择领域,但有一些不同的选择:

  • 投手
  • 耕地
  • 外野
  • ...

当第一创建的形式(用于显示),所述的运动是如在登记的数据的一部分进行传递:

$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

因此...终于找到了如何正确执行此操作。它需要订阅两个不同的事件。

第一次构建表单时,会将一些数据传递给它,因此,PRE_SET_DATA事件包含该数据,并且正如问题中所述,一切正常。

在表单提交的那一刻,它是第一个不使用数据创建的,因此在PRE_SET_DATA访问的数据将是无效的。在这种情况下,我们跳过表单定制:

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(); 
} 
0

为什么你需要一个事件来完成这样的任务?您可以定义表单类的buildForm()操作中的字段。要访问事件对象,只需使用$options['data']->getEvent()

+0

的'buildForm'方法被用来定义FormType,但不是这种类型的每个实体。因此,如果我要使用该表单的许多实例,那么如果在'buildForm'方法中定制事物,则它们将不会进行不同的配置(无论传递哪些数据)。 – Khepin

+0

那么,窗体就是在“构建”阶段创建的。要重用这种功能,您可以创建嵌入式表单“SportEventFormType”,并在那里传递$ sport对象。 –

相关问题