Symfony 3 - Form model data loses property values which are not represented by fields

前端 未结 3 574
有刺的猬
有刺的猬 2021-01-25 05:07

I have a controller action method which should handle a two-splitted form. Each form handles just a few properties of my Entity Workflow. After submitting the first

3条回答
  •  太阳男子
    2021-01-25 05:24

    How can I hold the property values of the $workflow submitted in the $firstFormPart when submitting the $secondFormPart?

    So here is my (unsatisfying) solution:

    1. I pass the current session as an option to my form class for the $secondFormPart which is the WorkflowTransitionsType class with passing it as an argument when calling createForm inside the Controller action method:

      $secondFormPart = $this->createForm(WorkflowTransitionsType::class, $workflow, array(
          'session'   => $this->get('session')
      ));
      
    2. I save the session as a private property inside the WorkflowTransitionsType class, save the passed workflow in the current session and retrieve it when buildForm gets called a 2. time when submitting the form:

      class WorkflowTransitionsType extends AbstractType {
      
          /**
           * @var Workflow
           */
          private $workflow;
      
          /**
           * @var Session
           */
          private $session;
      
          /**
           * {@inheritdoc}
           */
          public function buildForm(FormBuilderInterface $builder, array $options) {
      
              /** @var Workflow $workflow */
              $this->workflow = $options['data'];
      
              /** @var Session $session */
              $this->session = $options['session'];
      
              // If the workflow is stored in the session we know that this method is called a 2. time!
              if($this->session->has($this->getBlockPrefix() . '_workflow')) $this->workflow = $this->session->get($this->getBlockPrefix() . '_workflow');
      
                  $builder
                      ->setMethod('PATCH')
                      ->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
                          dump($event);
                          // This always gets called AFTER storing the workflow if it is present in the current session
                          $this->session->set($this->getBlockPrefix() . '_workflow', $this->workflow);
                      })
                      ->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) {
                          // Here we manipulating the passed workflow data by setting all previous values! 
                          $eventForm = $event->getForm();
      
                          /** @var Workflow $submitWorkflow */
                          $submitWorkflow = $eventForm->getData();
      
                          $submitWorkflow->setName($this->workflow->getName());
                          foreach($this->workflow->getStates() as $state) $submitWorkflow->addState($state);
      
                          $eventForm->setData($submitWorkflow);
                      })
                      ->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
                          // After submitting the workflow object is no longer required!
                          $this->session->remove($this->getBlockPrefix() . '_workflow');
                      })
                      ->add('initialState', ChoiceType::class, array(
                          ...
                          // Didn´t change (look at my question)
                      ))
                      ->add('transitions', CollectionType::class, array(
                          ...
                          // Didn´t change (look at my question)
                      ))
                      ->add('save', SubmitType::class, array(
                          ...
                          // Didn´t change (look at my question)
                      ));
          }
      
          /**
           * {@inheritdoc}
           */
          public function configureOptions(OptionsResolver $resolver) {
              $resolver->setDefaults(array(
                  'data_class'            => Workflow::class,
                  'translation_domain'    => 'MyBundle',
              ));
              $resolver->setRequired(array(
                  // This is necessary to prevent an error about an unknown option!
                  'session'
              ));
          }
      }
      

提交回复
热议问题