如何使用Symfony2表单清除字段值

时间:2022-10-16 18:15:47

I'm writing my own CAPTCHA class and when the form doesn't validate, I don't want to pre-populate the captcha input with the previous answer, for obvious reasons. I just want to the clear the input before it's rendered.

我正在编写自己的CAPTCHA类,当表单没有验证时,我不想用前面的答案预先填充验证码输入,原因很明显。我只想在渲染之前清除输入。

I've discovered the data option is only for the default value, which is overwritten by what the user enters. I tried the following code:

我发现数据选项仅用于默认值,该值由用户输入的内容覆盖。我尝试了以下代码:

$form->get('captcha')->setData(null);

.. After the request is bound with the form, but an AlreadyBoundException is thrown. I have actually managed to get it working with:

..请求与表单绑定后,但抛出AlreadyBoundException。我实际上设法让它与:

if (isset($formView->children['captcha'])) {
    $formView->children['captcha']->vars['value'] = null;
}

But that just looks wrong, and definitely not up to Symfony standards. I've looked through the other options you can provide when building the form, but I can't see anything of note.

但这看起来不错,绝对不符合Symfony标准。我已经查看了构建表单时可以提供的其他选项,但我看不到任何注意事项。

Does anyone have any idea?

有人有什么主意吗?

By the way, I half expect Symfony2 comes packaged with a CAPTCHA solution, this is mainly a learning exercise while I get used to the framework.

顺便说一句,我有一半期望Symfony2包含一个CAPTCHA解决方案,这主要是一个学习练习,而我习惯了框架。

3 个解决方案

#1


5  

I think you want to handle this form field like Symfony handles a password field: it won't get populated. Let's take a look at the PasswordType:

我想你想处理这个表单字段,如Symfony处理密码字段:它不会被填充。我们来看看PasswordType:

namespace Symfony\Component\Form\Extension\Core\Type;

class PasswordType extends AbstractType
{
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        if ($options['always_empty'] || !$form->isSubmitted()) {
            $view->vars['value'] = '';
        }
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'always_empty' => true,
            'trim' => false,
        ));
    }

    //...
}

So, it's pretty simple: just add $view->vars['value'] = '' in the buildView method of your FormType (i.e. CaptchaType). That means the data of the field is not being cleared, but it won't be passed to the Twig template. Different approach, but the result is the same: the password field stays empty after validation failed.

所以,它非常简单:只需在FormType的buildView方法中添加$ view-> vars ['value'] =''(即CaptchaType)。这意味着该字段的数据未被清除,但不会传递给Twig模板。不同的方法,但结果是相同的:验证失败后密码字段保持为空。

If you are really lazy, you can use the PasswordType, but since the input of that field will be masked (*****), will that make an annoying captcha field even worse.

如果你真的很懒,你可以使用PasswordType,但由于该字段的输入将被屏蔽(*****),这会使烦人的验证码字段更糟糕。

Your Form Type maybe look like this:

您的表单类型可能如下所示:

class CaptchaType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['value'] = '';
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return __NAMESPACE__.'\TextType';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->getBlockPrefix();
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'captcha';
    }
}

Edit: Just found that CaptchaBundle took the same approach.

编辑:刚刚发现CaptchaBundle采用了相同的方法。

#2


3  

There is a funny way to modify the Request before handling it. However I'd look into Stephan's answer as it seems more clean.

在处理请求之前,有一种有趣的方法可以修改请求。不过我会看看Stephan的答案,因为它看起来更干净。

Something like so:

像这样的东西:

public function indexAction(Request $request)
{

    $form = $this->createForm(Form::class);

    $subData=$request->request->get('form');

    $subData['task']=null;

    $request->request->set('form',$subData);

    $form->handleRequest($request);


    if ($form->isValid()) {

      //do stuff
    }


    return $this->render('default/index.html.twig', array(
        'form' => $form->createView()
    ));
}

Get submitted data with the name 'form' as an array of values, change the said value to null, then set the request's value with the new one and have the form handle it.

获取名为'form'的提交数据作为值数组,将所述值更改为null,然后使用新值设置请求的值并让表单处理它。

And a simple form

还有一个简单的形式

class Form extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('task')
            ->add('save', SubmitType::class);    

    }

}

No matter what you type, the data will always be null after submitting the form. Of course, you need to verify the captcha before setting the value to null.

无论您输入什么内容,提交表单后数据始终为空。当然,您需要在将值设置为null之前验证验证码。

#3


0  

You can pass an incomplete entity to the action called when your control finds form invalid.

当控件发现表单无效时,您可以将不完整的实体传递给调用的操作。

public function updateAction(Request $request, $id)
{
    $entity = $this->EM()->getRepository('Bundle:Entity')->find($id);
    if (!$entity) {
        throw $this->createNotFoundException('Unable to find Entity entity.');
    }

    $form = $this->createForm(new RecommendationType()
        ,$entity
        ,array(
            'attr'            => array(
                ,'entity'         => $entity
                )
            )
        );

    $form->bind($request);
    if ($form->isValid()) {
        $this->EM()->persist($entity);
        $this->EM()->flush();

        return $this->redirect($this->generateUrl('entity_show'
            ,array('id' => $id)));
    } else {
        $entity->setCapthca(Null);
    } 

    return $this->render('Bundle:Entity:edit.html.twig'
        ,array(
            'entity'            => $entity
            ,'form'             => $form->createView()
            )
        );
}

The create action would have similar modification.

创建操作将有类似的修改。

#1


5  

I think you want to handle this form field like Symfony handles a password field: it won't get populated. Let's take a look at the PasswordType:

我想你想处理这个表单字段,如Symfony处理密码字段:它不会被填充。我们来看看PasswordType:

namespace Symfony\Component\Form\Extension\Core\Type;

class PasswordType extends AbstractType
{
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        if ($options['always_empty'] || !$form->isSubmitted()) {
            $view->vars['value'] = '';
        }
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'always_empty' => true,
            'trim' => false,
        ));
    }

    //...
}

So, it's pretty simple: just add $view->vars['value'] = '' in the buildView method of your FormType (i.e. CaptchaType). That means the data of the field is not being cleared, but it won't be passed to the Twig template. Different approach, but the result is the same: the password field stays empty after validation failed.

所以,它非常简单:只需在FormType的buildView方法中添加$ view-> vars ['value'] =''(即CaptchaType)。这意味着该字段的数据未被清除,但不会传递给Twig模板。不同的方法,但结果是相同的:验证失败后密码字段保持为空。

If you are really lazy, you can use the PasswordType, but since the input of that field will be masked (*****), will that make an annoying captcha field even worse.

如果你真的很懒,你可以使用PasswordType,但由于该字段的输入将被屏蔽(*****),这会使烦人的验证码字段更糟糕。

Your Form Type maybe look like this:

您的表单类型可能如下所示:

class CaptchaType extends AbstractType
{
    /**
     * {@inheritdoc}
     */
    public function buildView(FormView $view, FormInterface $form, array $options)
    {
        $view->vars['value'] = '';
    }

    /**
     * {@inheritdoc}
     */
    public function getParent()
    {
        return __NAMESPACE__.'\TextType';
    }

    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return $this->getBlockPrefix();
    }

    /**
     * {@inheritdoc}
     */
    public function getBlockPrefix()
    {
        return 'captcha';
    }
}

Edit: Just found that CaptchaBundle took the same approach.

编辑:刚刚发现CaptchaBundle采用了相同的方法。

#2


3  

There is a funny way to modify the Request before handling it. However I'd look into Stephan's answer as it seems more clean.

在处理请求之前,有一种有趣的方法可以修改请求。不过我会看看Stephan的答案,因为它看起来更干净。

Something like so:

像这样的东西:

public function indexAction(Request $request)
{

    $form = $this->createForm(Form::class);

    $subData=$request->request->get('form');

    $subData['task']=null;

    $request->request->set('form',$subData);

    $form->handleRequest($request);


    if ($form->isValid()) {

      //do stuff
    }


    return $this->render('default/index.html.twig', array(
        'form' => $form->createView()
    ));
}

Get submitted data with the name 'form' as an array of values, change the said value to null, then set the request's value with the new one and have the form handle it.

获取名为'form'的提交数据作为值数组,将所述值更改为null,然后使用新值设置请求的值并让表单处理它。

And a simple form

还有一个简单的形式

class Form extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('task')
            ->add('save', SubmitType::class);    

    }

}

No matter what you type, the data will always be null after submitting the form. Of course, you need to verify the captcha before setting the value to null.

无论您输入什么内容,提交表单后数据始终为空。当然,您需要在将值设置为null之前验证验证码。

#3


0  

You can pass an incomplete entity to the action called when your control finds form invalid.

当控件发现表单无效时,您可以将不完整的实体传递给调用的操作。

public function updateAction(Request $request, $id)
{
    $entity = $this->EM()->getRepository('Bundle:Entity')->find($id);
    if (!$entity) {
        throw $this->createNotFoundException('Unable to find Entity entity.');
    }

    $form = $this->createForm(new RecommendationType()
        ,$entity
        ,array(
            'attr'            => array(
                ,'entity'         => $entity
                )
            )
        );

    $form->bind($request);
    if ($form->isValid()) {
        $this->EM()->persist($entity);
        $this->EM()->flush();

        return $this->redirect($this->generateUrl('entity_show'
            ,array('id' => $id)));
    } else {
        $entity->setCapthca(Null);
    } 

    return $this->render('Bundle:Entity:edit.html.twig'
        ,array(
            'entity'            => $entity
            ,'form'             => $form->createView()
            )
        );
}

The create action would have similar modification.

创建操作将有类似的修改。