symfony2 表单

正常情况下我还是更喜欢直接写表单而不是使用symfony内置的表单对象来穿件表单,但当我一个表单比较重要,需要csrf保护的时候 我会选择使用这种方法来表单。

官方文档有介绍一大堆通过类创建表单这里我就不想在这块多说。只为直接快速使用:

使用一个无底层类表单:

<?php

namespace Cellcom\WebBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;

class DefaultController extends BaseController
{public function formAction(Request $request){
        $form = $this->createFormBuilder()
                     ->add('password', 'password')
                     ->add('email', 'text')->getForm();
        if($request->getMethod() == "POST"){
              $form->bind($request);

              if($form->isValid()){
                     //执行一些行为,比如保持task到数据库
            $data = $form->getData();
                     return $this->redirect($this->generateUrl('cellcom_web_homepage'));
              }
        }
        return $this->render('CellcomWebBundle:Default:form.html.twig',array(
               'form' =>$form->createView(),
        ));
        // dump($form);
        // exit();
    }
}

默认情况下,一个表单真的假设你想要一个数据数组而不是数据对象。

  这里有两种方式你可以改变它的行为并绑定一个对象;
    1.当创建表单时传入一个对象(作为createFormBuilder的第一个参数或者createForm的第二个参数)。
    2.在你的表单中声明data_class 选项

  如果以上两种方式都没有,那么表单会返回一个数组数据。在这个示例中因为$defaultData不是一个对象,又没有设置data_class选项,则$form->getData()最终返回一个数组。

在模板中渲染表单:

<form action="{{ path('form_test') }}" method ="post" {{ form_enctype(form) }}>
    {{ form_widget(form) }}

     <input type="submit" />
</form>

  form_enctype(form) 只要有一个字段是文件上传,那么它就会义务的设置为 enctype="multipart/form-data";
  form_errors(form) 渲染任何整个form的任何错误信息(特定字段的错误,会显示在每个字段的下面一行)。
  form_row(form.dueDate) 默认情况下,为给定的字段在一个div中渲染一个文本标签,任何错误,和HTML表单部件。
  form_rest(form) 渲染没有指出的其余任何字段,通常在表单的末尾调用它防止遗忘或者渲染一些你不愿意手动设置的隐藏字段。它同时还能为我们提供CSRF保护。

  大部分工作是由form_row帮助方法类完成的,它默认在一个div中为每个字段渲染显示标签,错误信息和HTML表单部件。
  注意,你可以通过form.vars.value 来访问你当前是表当数据:

{{ form.vars.value.task }}

手工渲染每一个表单字段
  form_row帮助器能让你很快的渲染你表单中的每一个字段,并且每一行可以被自定义化。但是生活不总是那么简单的,你也可能要手动的渲染每一个字段。
Twig格式:

复制代码
{{ form_errors(form) }}

<div>
    {{ form_label(form.task) }}
    {{ form_errors(form.task) }}
    {{ form_widget(form.task) }}
</div>

<div>
    {{ form_label(form.dueDate) }}
    {{ form_errors(form.dueDate) }}
    {{ form_widget(form.dueDate) }}
</div>

{{ form_rest(form) }}
复制代码

 改变标签

{{ form_label(form.task, '任务') }}

给field添加额外属性

{{ form_widget(form.task, {'attr': {'class': 'task_field'}}) }}

你也可以直接获取field属性值

{{ form.task.vars.id }}
{{ form.task.vars.full_name }}

 

 

CSRF 保护
  CSRF--Cross-site request forgery,跨站伪造请求 是恶意攻击者试图让你的合法用户在不知不觉中提交他们本不想提交的数据的一种方法。
幸运的是,CSRF攻击可以通过在你的表单中使用CSRF 记号来阻止。

  默认情况下,Symfony自动为你嵌入一个合法的CSRF令牌。这就意味着你不需要做任何事情就可以得到CSRF保护。CSRF保护是通过在 你的表单中添加一个隐藏字段,默认的名叫_token。它包含一个值,这个值只有你和你的用户知道。这确保了是用户而不是其它实体在提交数据。 Symfony自动校验该token是否存在以及其准确性。

  _token 字段是一个隐藏字段并且会自动的渲染,只要你在你的模板中包含了form_rest()函数。它确保了没有被渲染过的字段全部渲染出来。CSRF令牌可以按照表单来个性化,比如:

复制代码
class TaskType extends AbstractType
{
      // ...

      public function getDefaultOptions(array $options)
      {
           return array(
                   'data_class' => 'Acme\TaskBundle\Entity\Task',
                   'csrf_protection' => true,
                   'csrf_field_name' => '_token',
                   // 一个唯一的键值来保证生成令牌
                   'intention' => 'task_item',
           );
      }

      // ...
}
复制代码

  要关闭CSRF保护,设置csrf_protection 选项为false。intentsion选项是可选的,但为不同的表单生成不同的令牌极大的加强了安全性。

 

posted @ 2016-03-23 16:22  jyLi  阅读(766)  评论(0编辑  收藏  举报