Symfony2 - 如何阻止表单>handleRequest使帖子数据中不存在的字段清空

2022-08-30 15:14:33

我有一个在Symfony中构建的表单,当在视图中呈现时,html表单可能包含也可能不包含表单对象中的所有字段(实体类型具有几个不同的状态,并且并非所有字段都在视图中展开)。

问题是,当在提交处理程序中通过表单对象的 handleRequest() 方法处理表单时,它会将实体中不存在的任何属性重置为 null,从而丢弃任何现有值。

有没有办法告诉Symfony不要那么愚蠢,只处理POST数据中存在的字段?

或者,我是否必须在 handleRequest 调用之前克隆实体,然后遍历 POST 值,并将相关值从后 handleRequest 实体复制到实体的 pre-handleRequest 克隆,因此我保留了不在 POST 数据中的字段。

唷!正如你所看到的,这是一个愚蠢的解决方案,有点愚蠢的问题,tbh。

如果实体实际上是一个新创建的对象,但我可以从数据库加载,然后调用 handleRequest,我可以理解 symfony 这样做 - 它应该足够明智,知道对象已经初始化并且只设置 POST 数据中传递的字段。

感谢您的任何帮助。

问候

史蒂夫。


答案 1

简而言之,不要使用 .handleRequest

应直接使用,并将参数设置为 false。submitclearMissing

Symfony/Component/Form/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。


答案 2

如果您的实体具有不同的状态,则可以在表单类型中反映这一点。

创建包含不同字段设置的多个表单类型(可能使用继承),并在控制器中实例化所需的表单类型。

像这样:

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)来修改表单。

您可以在文档中找到解释和示例


推荐