11

我正在编写自己的 CAPTCHA 类,当表单无法验证时,出于显而易见的原因,我不想用之前的答案预先填充验证码输入。我只想在渲染之前清除输入。

我发现data选项仅适用于默认值,它会被用户输入的内容覆盖。我尝试了以下代码:

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

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

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

但这看起来是错误的,而且绝对不符合 Symfony 的标准。我查看了您在构建表单时可以提供的其他选项,但我看不到任何值得注意的东西。

有谁有想法吗?

顺便说一句,我有一半希望 Symfony2 附带一个 CAPTCHA 解决方案,这主要是我习惯该框架时的学习练习。

4

3 回答 3

5

我想你想像 Symfony 处理一个字段一样处理这个表单password字段:它不会被填充。让我们看一下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,
        ));
    }

    //...
}

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

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

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

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

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

于 2016-05-04T15:21:01.793 回答
3

有一种有趣的方法可以在处理请求之前对其进行修改。但是,我会研究斯蒂芬的答案,因为它看起来更干净。

像这样:

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()
    ));
}

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

和一个简单的形式

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

    }

}

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

于 2016-05-04T19:38:00.340 回答
0

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

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()
            )
        );
}

create 动作会有类似的修改。

于 2013-02-22T08:20:10.103 回答