Error matching existing object with inline form in symfony2

I have an entity that is on the back of three one-to-one mappings. The FittingStep object FittingStep displayed by FittingStepSingleValue , etc. FittingStep has a fittingStepType field that identifies which of the three objects FittingStep should look for. I want to insert this object into the FittingStep edit FittingStep .

I defined forms as services for each of the subforms:

 services: ihear.form.fitting_step_single_value: class: Ihear\FittingBundle\Form\FittingStepSingleValueType arguments: [@security.context] tags: - name: form.type alias: ihear_fittingbundle_fittingstepsinglevaluetype ihear.form.fitting_step_double_value: class: Ihear\FittingBundle\Form\FittingStepDoubleValueType arguments: [@security.context] tags: - name: form.type alias: ihear_fittingbundle_fittingstepdoublevaluetype ihear.form.fitting_step_option: class: Ihear\FittingBundle\Form\FittingStepOptionType arguments: [@security.context] tags: - name: form.type alias: ihear_fittingbundle_fittingstepoptiontype 

These service classes look like this (pretty simple) 

 class FittingStepSingleValueType extends AbstractType { private $securityContext; public function __construct(SecurityContext $securityContext) { $this->securityContext = $securityContext; } public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('max1') ->add('description1') ->add('fittingStep', 'hidden') ; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Ihear\FittingBundle\Entity\FittingStepSingleValue' )); } public function getName() { return 'ihear_fittingbundle_fittingstepsinglevaluetype'; } } 

My form uses the EventListener in PRE_SET_DATA to add the appropriate field of the inline form:

 class FittingStepType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('name') ->add('abbreviation') ->add('description') ->add('fittingStepType', 'choice', ['choices' => ['SingleValue' => 'SingleValue', 'DoubleValue' => 'DoubleValue', 'Option' => 'Option'], 'empty_value' => 'select one please']) ; $formModifier = function(FormInterface $form, $fittingStepType) { switch ($fittingStepType) { case 'SingleValue': $form->add('fittingStepSingleValue', 'ihear_fittingbundle_fittingstepsinglevaluetype'); if ($form->has('fittingStepDoubleValue')) $form->remove('fittingStepDoubleValue'); if ($form->has('fittingStepOption')) $form->remove('fittingStepOption'); break; case 'DoubleValue': $form->add('fittingStepDoubleValue', 'ihear_fittingbundle_fittingstepdoublevaluetype'); if ($form->has('fittingStepSingleValue')) $form->remove('fittingStepSingleValue'); if ($form->has('fittingStepOption')) $form->remove('fittingStepOption'); break; case 'Option': $form->add('fittingStepOption', 'ihear_fittingbundle_fittingstepoptiontype'); if ($form->has('fittingStepSingleValue')) $form->remove('fittingStepSingleValue'); if ($form->has('fittingStepDoubleValue')) $form->remove('fittingStepDoubleValue'); break; } }; $builder->addEventListener( FormEvents::PRE_SET_DATA, function(FormEvent $event) use ($formModifier) { $form = $event->getForm(); // this is the FittingStep $data = $event->getData(); // this is the Entity that contains the value(s) // ie FittingStepSingleValue $fittingStepType = $data->getFittingStepType(); switch ($fittingStepType) { case 'SingleValue': $formModifier($form, $fittingStepType); break; case 'DoubleValue': $formModifier($form, $fittingStepType); break; case 'Option': $formModifier($form, $fittingStepType); break; } } ); } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Ihear\FittingBundle\Entity\FittingStep' )); } public function getName() { return 'ihear_fittingbundle_fittingsteptype'; } } 

My controller for the edit action:

 /** * Displays a form to edit an existing FittingStep entity. * * @Route("/{id}/edit", name="admin_fittingstep_edit") * @Method("GET") * @Template() */ public function editAction($id) { $em = $this->getDoctrine()->getManager(); $entity = $em->getRepository('IhearFittingBundle:FittingStep')->find($id); if (!$entity) { throw $this->createNotFoundException( 'Unable to find FittingStep entity.'); } $editForm = $this->createForm(new FittingStepType(), $entity); $deleteForm = $this->createDeleteForm($id); return array( 'entity' => $entity, 'edit_form' => $editForm->createView(), 'delete_form' => $deleteForm->createView(), ); } 

When I try to load a form, I get an exception:

It is expected that the data of the form type will be of the scalar, array, or instance \ ArrayAccess type, but is an instance of the class Ihear \ FittingBundle \ Entity \ FittingStep. You can avoid this error by setting the "data_class" option for "Ihear \ FittingBundle \ Entity \ FittingStep" or by adding a transformer view that converts an instance of the Ihear \ FittingBundle \ Entity \ FittingStep class for a scalar, array, or instance from \ ArrayAccess.

What am I doing wrong? There seems to be some connection between matching objects between objects and displaying on the form. As a side note, I have successfully used the closure of $formModifier in my create form, so it works great when creating a new object with an inline form.

+6
source share
2 answers

I understood the problem. The relationship between the objects was indicated by the inline object, so I added a hidden field for the parent object in the inline form. This little rascal did not cause problems with the creation form, but caused the error above when I inserted a form to edit an existing object. Thanks to @albert for pointing me to this line of code!

 class FittingStepSingleValueType extends AbstractType { private $securityContext; public function __construct(SecurityContext $securityContext) { $this->securityContext = $securityContext; } public function buildForm(FormBuilderInterface $builder, array $options) { $builder ->add('max1') ->add('description1') // this line was the culprit //->add('fittingStep', 'hidden') ; } public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'data_class' => 'Ihear\FittingBundle\Entity\FittingStepSingleValue' )); } public function getName() { return 'ihear_fittingbundle_fittingstepsinglevaluetype'; } } 
+1
source

You must update fittinStep from hidden in Collection

 ->add('fittingStep', 'hidden') 

Collection of documents http://symfony.com/doc/current/reference/forms/types/collection.html

 ->add('fittingStep', 'collection', array('type'=>new FittingStepType(), 'label'=>false)) 
+1
source

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


All Articles