PHP-Symfony 3-表单模型数据丢失了属性值,这些属性值未由字段表示

我有一个控制器操作方法,该方法应该处理两个分割的表格.每个表单仅处理我的实体工作流的一些属性.提交第一个表单后,我可以毫无问题地创建和呈现第二个表单.现在的问题是:

提交第二种形式后,第一种形式中设置的所有值的信息都消失了,这意味着在调用Submit(或handleRequest在这里没有任何区别)时,实体对象仅保存第一种形式中设置的属性的数据,并且甚至无法正确解析某些值.

这是控制器(带有一些注释):

public function createWorkflowAction(Request $request, Project $project, Workflow $workflow = null) {   

    if(!$workflow) {
        $workflow = new Workflow($project);
    }

    $firstFormPart = $this->createForm(WorkflowStatesType::class, $workflow);

    // $firstFormPart->handleRequest($request);
    $firstFormPart->submit($request->get($firstFormPart->getName()), false);

    $secondFormPart = $this->createForm(WorkflowTransitionsType::class, $workflow);
    // secondFormPart is created correct with all values after submitting $firstFormPart and calling submit

    if($firstFormPart->isSubmitted() && $firstFormPart->isValid()) {
        return $this->render('@MyBundle/Workflow/workflow_edit_create_second_part.html.twig', array(
            'form'   => $secondFormPart->createView(),
        ));
        // This will render correctly with all values submitted in the $firstFormPart
    }

    $secondFormPart->submit($request->get($secondFormPart->getName()), false);
    // $secondFormPart->handleRequest($request);
    // HERE IS THE PROBLEM -> After submitting the $secondFormPart all property values set in the $firstFormPart are gone

    if($secondFormPart->isSubmitted() && $secondFormPart->isValid()) {
        dump($workflow);
        die();
    }

    return $this->render('@MyBundle/Workflow/workflow_edit_create_first_part.html.twig', array(
        'form' => $firstFormPart->createView(),
    ));
}

WorkflowStatesType:

class WorkflowStatesType extends AbstractType {

        /**
         * @var \Doctrine\ORM\Mapping\ClassMetadata
         */
        private $classMetadata;

        /**
         * WorkflowType constructor.
         * @param EntityManager $em
         */

        public function __construct(EntityManager $em) {
            $this->classMetadata = $em->getClassMetadata(Workflow::class);
        }

        public function buildForm(FormBuilderInterface $builder, array $options) {
            $builder
                ->setMethod('PATCH')
                ->add('name', TextType::class, array(
                    'label' => 'nameTrans',
                    'attr'  => array('maxLength' => $this->classMetadata->getFieldMapping('name')['length']),
                ))
                ->add('states',  CollectionType::class, array(
                    'entry_type'        => StateType::class,
                    'allow_add'         => true,
                    'error_bubbling'    => false,
                    'by_reference'      => false,
                    'label'             => 'workflowStatesTrans',
                ))
                ->add('next', SubmitType::class, array(
                    'label' => 'nextFormPartTrans',
                ));
        }

        public function configureOptions(OptionsResolver $resolver) {
            $resolver->setDefaults(array(
                'data_class'            => Workflow::class,
                'translation_domain'    => 'My_Bundle',
            ));
        }

    }

WorkflowTransitionsType:

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

                $builder
                    ->setMethod('PATCH')
                    ->add('initialState', ChoiceType::class, array(
                        'choices'           => $this->workflow->getStates(),
                        'choice_label'      => function($state) {
                            return ($state && $state instanceof State) ? $state->getStatekey() : 'noval';
                        },
                        'choice_value'      => function($state) {
                            return ($state && $state instanceof State) ? $state->getStatekey() : 'noval';
                        },

                        // This combination of 'expanded' and 'multiple' implements a select Box
                        'expanded'          => false,
                        'multiple'          => false,
                    ))
                    ->add('transitions', CollectionType::class, array(
                        'entry_type'        => TransitionType::class,
                        'allow_add'         => true,
                        'allow_delete'      => true,
                        'error_bubbling'    => false,
                        'by_reference'      => false,
                        'label'             => 'transitionsTrans',
                        'entry_options'     => array(
                            'states'    => $this->workflow->getStates(),
                        ),
                    ))
                    ->add('save', SubmitType::class, array(
                        'label'             => 'submitTrans',
                    ));
        }

        public function configureOptions(OptionsResolver $resolver) {
            $resolver->setDefaults(array(
                'data_class'            => Workflow::class,
                'translation_domain'    => 'My_Bundle',
            ));
            $resolver->setrequired(array(
                'session'
            ));
        }
    }

提交$secondFormPart时,如何保存在$firstFormPart中提交的$workflow的属性值?

解决方法:

由于仅使用secondForm数据再次提交表单,因此您将丢失firstForm数据.

您有3种方法来保留它们:

1)将firstForm中的数据设置为查询

// Insert that instead of the `return $this->render` for the second form
$url = $this->generateUrl(
    $request->attributes->get('_route'),
    array_merge(
        $request->query->all(),
        array('secondForm' => true, 'name' => $workflow->getName(), 'states' => $workflow->getStates()) // change the param
    )
);
return $this->redirect($url);

在$secondFormPart = $this-> createForm(WorkflowTransitionsType :: class,$workflow)之前;

名称和状态重新设置为$workflow实体,在此示例中,您可以检查查询变量secondForm以了解是否提交了第一个表单

2)使用一些隐藏字段将数据从firstForm设置到下一个PATCH请求中

您必须修改secondForm以处理来自带hidden form type的firstForm的数据

3)在返回第二个表单之前在会话中设置数据

首先,您的实体将必须实现Serializable接口,并声明方法serialize和unserialize

像那样

$this->get('session')->set('workflow', $workflow);

序列化方法将用于存储它.

您可以使用反序列化方法设置回去

$session = $this->get('session');
$workflow = new Workflow();
$workflow->unserialize($session->get('workflow'));

因为您将整个实体存储在会话中,所以此解决方案将大大降低应用程序的性能

相关文章

统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...
前言 之前做了微信登录,所以总结一下微信授权登录并获取用户...
FastAdmin是我第一个接触的后台管理系统框架。FastAdmin是一...
之前公司需要一个内部的通讯软件,就叫我做一个。通讯软件嘛...
统一支付是JSAPI/NATIVE/APP各种支付场景下生成支付订单,返...