Symfony2: transformFailure "Compound forms expect an array or NULL on presentation."

I have a Location object consisting of 6 fields. Some of these fields are optional.

So, I have a LocationSelectType that fills in the fields depending on the location in the PRE_SET_DATA and PRE_SUBMIT events. This works fine.

But in PRE_SUBMIT, I would also like to create a Location object from the data entered by the user. This seems to work, but causes an error at the end: * transformFailure "Compound forms expect an array or NULL when submitted." *

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'; } 

Controller:

 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, )); } 

When I reset the form in the controller, I see:

 -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 
+5
source share
1 answer

Your problem here

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

In $event->setData($location); you made a mistake: in the event pre_submit $event->getData() is an associative array, not an entity (see https://symfony.com/doc/current/form/events.html#component-form-event-table ) so you must set the associative array to $event->setData() . Try calling dump($event->getData()) and see the expected format.

+1
source

Source: https://habr.com/ru/post/1213813/


All Articles