Symfony2关于Form工作方式的澄清



在我在网上看到的许多例子中,在持久化表单之前,不需要获取表单的内容。例如:

public function FormulaireAction(Request $request)
{
    $exemple= new Example();
    $form = $this->createForm('example',$exemple);
    $form->handleRequest($request);
    if($form->isValid()){
                      //$exemple = $form->getData(); not needed
                      $this->manager->save($exemple);
        }         
}

大多数时候这是真的,但当我将表单的数据修改为FormEvent::SUBMIT事件时,就像这样:

public function onSubmit(FormEvent $event){
   $form = $event->getForm();
   $data = $event->getData();
   //find Example that fit the form data
   $exemple= $this->em->getRepository('MyExemple:exemple')->findExample($data);
   //replace with the  object location
   $form->setData($exemple);
}

我需要手动执行$form->getData(),因为表单没有将默认对象更新为新的

public function ExempleAction(Request $request)
{
    $exemple= new Exemple();
    $form = $this->createForm('exemple_type',$exemple);
    $form->handleRequest($request);
    if($form->isValid()){
                        dump($exemple); //return default empty object
                        dump($form->getData()); //return the object created into the formType
        }         
}

这是正常行为还是我做错了什么?

编辑:复制问题的完整FormType代码

class LocationSelectorType extends AbstractType{
public $em;
private $router;
private $options;
public function __construct(EntityManager $em,Router $router)
{
    $this->em = $em;
    $this->router = $router;
}
/**
 * @param FormBuilderInterface $builder
 * @param array $options
 */
public function buildForm(FormBuilderInterface $builder, array $options)
{
    $em = $this->em;
    $builder   
        ->add('country','choice',array(
            'choices'=>$this->em->getRepository('MyWorldBundle:Country')->findCountryList('id'),
            'required'=>false,
            'mapped'=>false,
            'empty_value'=>'Votre pays',
            'attr'=>array('class'=>'geo-select geo-select-country geo-select-ajax','data-geo-level'=>'country','data-icon'=>'globe','data-ajax-url'=>$options['ajax_url'],'style'=>"width:100%"),
            ))
        ->add('region','choice',array(
            'choices'=>array(),
            'required'=>false,
            'mapped'=>false,
            'empty_value'=>'Votre région',
            'attr'=>array('class'=>'geo-select geo-select-region geo-select-ajax hide','data-geo-level'=>'region','data-icon'=>'globe','data-ajax-url'=>$options['ajax_url'],'style'=>"width:100%"),
            ))
        ->add('departement','choice',array(
            'choices'=>array(),
            'required'=>false,
            'mapped'=>false,
            'empty_value'=>'Votre Département',
            'attr'=>array('class'=>'geo-select geo-select-departement geo-select-ajax hide','data-geo-level'=>'departement','data-icon'=>'globe','data-ajax-url'=>$options['ajax_url'],'style'=>"width:100%"),
            ))
        ->add('district','choice',array(
            'choices'=>array(),
            'required'=>false,
            'mapped'=>false,
            'empty_value'=>'Votre district',
            'attr'=>array('class'=>'geo-select geo-select-district geo-select-ajax hide','data-geo-level'=>'district','data-icon'=>'globe','data-ajax-url'=>$options['ajax_url'],'style'=>"width:100%"),
            ))
        ->add('division','choice',array(
            'choices'=>array(),
            'required'=>false,
            'mapped'=>false,
            'empty_value'=>'Votre division',
            'attr'=>array('class'=>'geo-select geo-select-division geo-select-ajax hide','data-geo-level'=>'division','data-icon'=>'globe','data-ajax-url'=>$options['ajax_url'],'style'=>"width:100%"),
            ))
        ->add('city','choice',array(
            'choices'=>array(),
            'required'=>false,
            'mapped'=>false,
            'empty_value'=>'Votre ville',
            'attr'=>array('class'=>'geo-select geo-select-city geo-select-ajax hide','data-geo-level'=>'city','data-icon'=>'globe','data-ajax-url'=>$options['ajax_url'],'style'=>"width:100%"),
            ))             
    ;
    $this->options = $options;
    $builder->addEventListener(FormEvents::PRE_SET_DATA, array($this, 'onPreSetData'));
    $builder->addEventListener(FormEvents::PRE_SUBMIT, array($this, 'onPreSubmit'));
    $builder->addEventListener(FormEvents::SUBMIT, array($this, 'onSubmit'));
    $builder->addEventListener(FormEvents::POST_SUBMIT, array($this, 'onPostSubmit'));
}
public function onPreSetData(FormEvent $event)
{
    $form = $event->getForm();
    $location = $event->getData(); 
    //dynamilcaly fill fields     
    $this->addGeoFields($form, $location);
}    

public function onPreSubmit(FormEvent $event)
{
    $form = $event->getForm();
    $data = $event->getData(); 
    //find or create the Location object taht fits the data
    $this->location = $this->em->getRepository('MyWorldBundle:Location')->findLocationFromStates($data);
    //dynamilcaly fill fields   
    $this->addGeoFields($form, $this->location);
}
public function onSubmit(FormEvent $event)
{
    $form = $event->getForm();
    $data = $event->getData();

    $event->setData($this->location);
}
public function onPostSubmit(FormEvent $event)
{
    $form = $event->getForm();
    $data = $event->getData();
}
//add fields that fits the Location
public function addGeoFields(FormInterface $form, $location)
{        
    if(is_object($location) && $location->isNull()) return;        
    if(NULL == $location) return;        
    if($location->getRegion()!=NULL) $this->addGeoField($form, $location, 'region', $location->getRegion()->getId());            
    if($location->getDepartement()!=NULL) $this->addGeoField($form, $location, 'departement', $location->getDepartement()->getId());
    if($location->getDistrict()!==NULL) $this->addGeoField($form, $location, 'district', $location->getDistrict()->getId());            
    if($location->getDivision()!==NULL) $this->addGeoField($form, $location, 'division', $location->getDivision()->getId());            
    if($location->getCity()!==NULL) $this->addGeoField($form, $location, 'city', $location->getCity()->getId());
}
//add one Location field
public function addGeoField(FormInterface $form, $location, $level, $value = '')
{        
    $list = $this->em->getRepository('MyWorldBundle:Location')->findStatesListFromLocationByLevel($location,$level);
    if(empty($list)) return;
    $form->add($list['level'],'choice',array(
            'choices'=>$list['list'],
            'required'=>false,
            'mapped'=>false,
            'empty_value'=>'Votre '.$list['level'],
            'attr'=>array('class'=>'geo-select geo-select-'.$list["level"].' geo-select-ajax','data-geo-level'=>$list["level"],'data-icon'=>'globe','data-ajax-url'=>$this->options['ajax_url'],'style'=>"width:100%"),
            'data'=>$value
            ));
}
/**
 * @param OptionsResolverInterface $resolver
 */
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'MyWorldBundleEntityLocation',
        'ajax_url' => $this->router->generate('my_world_location_select_nextlevel'),            
    ));
}
/**
 * @return string
 */
public function getName()
{
    return 'location_selector';
}}

您应该使用$event->setData($exemple)而不是$form->setData($exemple),因为标准化数据和非标准化数据存储在不同的位置:

public function onPreSubmit(FormEvent $event){
   $data = $event->getData();
   //find Example that fit the form data
   $exemple= $this->em->getRepository('MyExemple:exemple')->findExample($data);
   //replace with the  object location
   $event->setData($exemple);
}

最新更新