我有一个控制器操作方法,该方法应该处理两个分割的表格.每个表单仅处理我的实体工作流的一些属性.提交第一个表单后,我可以毫无问题地创建和呈现第二个表单.现在的问题是:
提交第二种形式后,第一种形式中设置的所有值的信息都消失了,这意味着在调用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种方法来保留它们:
// 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'));