我有一个在Symfony中构建的表单,当在视图中呈现时,html表单可能包含也可能不包含表单对象中的所有字段(实体类型有几个不同的状态而不是所有字段都在视图中呈现。)
问题在于,当表单在提交处理程序中处理时,通过表单对象的handleRequest()方法,它将实体中不存在于post数据中的任何属性重置为null,从而吹走任何现有值
有没有办法告诉Symfony不要这么愚蠢,只处理POST数据中的字段?
或者我必须在handleRequest调用之前克隆实体,然后循环POST值并将post-handleRequest实体中的相关值复制到实体的pre-handleRequest克隆,所以我保留了那些字段不属于POST数据。
唷!正如你所看到的,它有点愚蠢的解决方案,有点愚蠢的问题,tbh。
如果实体实际上是一个新创建的对象,我可以理解symfony这样做,但是它已经从DB加载然后调用了handleRequest - 知道该对象已经初始化并且只设置字段应该是明智的传递了POST数据。
感谢您的帮助。
此致
史蒂夫。
答案 0 :(得分:48)
简而言之,请勿使用handleRequest
。
您应直接使用submit
,并将clearMissing
参数设置为false。
的Symfony /组件/窗体/ FormInterface
/**
* Submits data to the form, transforms and validates it.
*
* @param null|string|array $submittedData The submitted data.
* @param bool $clearMissing Whether to set fields to NULL
* when they are missing in the
* submitted data.
*
* @return FormInterface The form instance
*
* @throws Exception\AlreadySubmittedException If the form has already been submitted.
*/
public function submit($submittedData, $clearMissing = true);
当您使用handleRequest
时,它会计算出您想要提交的数据,然后使用$form->submit($data, 'PATCH' !== $method);
提交,这意味着除非您使用PATCH
方法提交了表单,否则将清除领域。
要自行提交表单而不清除可以使用...
$form->submit($request->get($form->getName()), false);
..从请求中获取表单数据数组并直接提交,但明确缺少字段参数设置为false。
答案 1 :(得分:3)
如果您的实体具有不同的状态,则可以在表单类型中反映出来。
创建包含不同字段设置的多种表单类型(可能使用继承),并在控制器中实例化所需的表单类型。
这样的事情:
class YourState1FormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('someField')
;
}
}
class YourState2FormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('someOtherField')
;
}
}
或者在控制器中创建时将参数传递给单个表单类型,并根据状态调整字段设置。如果您不添加不存在的字段,则不会对其进行处理。
这样的事情:
class YourFormType extends AbstractType {
public function buildForm(FormBuilderInterface $builder, array $options)
{
if($options['state'] == 'state1') {
$builder
->add('someField')
;
} else if($options['state'] == 'state2') {
$builder
->add('someOtherField')
;
}
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'state' => 'state1'
));
}
}
<强>更新强>
您可以根据提交的数据修改表单的另一种方法是将事件侦听器注册到表单的PRE_SET_DATA和POST_SUBMIT事件。这些侦听器在表单提交过程中的不同时刻被调用,并允许您根据在表单创建时传递给表单类型的数据对象(PRE_SET_DATA)或用户提交的表单数据(POST_SUBMIT)来修改表单。
您可以找到解释和示例in the docs。