2015-02-20 19 views
5

6 alandan oluşan bir Konum nesnesine sahibim. Bu alanların bazıları isteğe bağlıdır. Symfony2: transformationFailure "Bileşik formlar, bir dizi veya NULL gönderiminde bekler."

Yani ben PRE_SET_DATA ve PRE_SUBMIT olaylara Yer bağlı alanları, doldurmak bir LocationSelectType var. Bu iyi çalışıyor.

Ama PRE_SUBMIT üzerinde

, ben de kullanıcının girdiği verilerden Yer nesnesi oluşturmak istiyoruz. Bu çalışır, ancak sonunda bir hata tetikler gözükmektedir: * transformationFailure "Bileşik şekilleri sunulması üzerine bir dizi veya NULL bekliyoruz." *

class LocationSelectType 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();, 
      '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(), //populate on events 
      '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(), //populate on events 
      '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(), //populate on events 
      '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(), //populate on events 
      '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(), //populate on events 
      '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::POST_SUBMIT, array($this, 'onPostSubmit')); 
} 

public function onPreSetData(FormEvent $event) 
{ 
    $form = $event->getForm(); 
    $location = $event->getData(); 

    //populate geo fields 
    $this->addGeoFields($form, $location); 

}  

public function onPreSubmit(FormEvent $event) 
{ 
    $form = $event->getForm(); 
    $data = $event->getData(); 


    //find Location that fit the form data 
    $location = $this->em->getRepository('MyWorldBundle:Location')->findLocationFromData($data); 

    //populate all relevant geo field to render the form view 
    $this->addGeoFields($form, $location); 

    //replace data with the object location 
    $event->setData($location); 


} 

public function onPostSubmit(FormEvent $event) 
{ 
    $form = $event->getForm(); 
    $data = $event->getData(); 

} 

public function addGeoFields(FormInterface $form, $location) 
{ 
    if($location == NULL) return; 

    if($location->getCountry() != NULL) $this->addGeoField($form, $location, 'country', $location->getCountry()->getCode());       
    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()); 
} 

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' => 'My\WorldBundle\Entity\Location', 
     'ajax_url' => $this->router->generate('my_world_location_select_nextlevel'), 
     'allow_extra_fields' => true, 
    )); 
} 

/** 
* @return string 
*/ 
public function getName() 
{ 
    return 'location_select'; 
} 

kontrolör:

public function formSelectLocationAction(Request $request) 
{ 

    $location = new Location(); 
    $form = $this->createForm('location_select',$location); 

    $form->handleRequest($request); 

    if($form->isValid()){ //form is not valid 

      $location = $form->getData(); 
    } 

    //dump($form); 

    return $this->render('MyWorldBundle:Form:test_location_select.html.twig',array(
     'form' => $form->createView(), 
     'location' => $location, 
     )); 
} 

i formu dökümü zaman denetleyicisi i bkz:

-transformationFailure: TransformationFailureException { 
#message: "Compound forms expect an array or NULL on submission." 
#code : 0 
#file: "C:\App\wamp\www\WeSport-symfony\path\vendor\symfony\symfony\src\Symfony\Component\Form\Form.php" 
##line: 565 

cevap

1

Sorununuz burada

public function onPreSubmit(FormEvent $event) { 
    $form = $event->getForm(); 
    $data = $event->getData(); //find Location that fit the form data 
    $location = $this->em->getRepository('MyWorldBundle:Location')->findLocationFromData($data) ; //populate all relevant geo field to render the form view 
    $this->addGeoFields($form, $location); //replace data with the object location 
    $event->setData($location); 
} 
olduğunu

$event->setData($location); içinde hata yaptınız: pre_submit olayında, $event->getData() ilişkisel bir dizidir, bir varlık değil (bkz. https://symfony.com/doc/current/form/events.html#component-form-event-table), bu nedenle $event->setData() içinde bir ilişkisel dizi belirlemelisiniz. dump($event->getData()) numaralı telefonu arayın ve beklenen biçime bakın.