正常状况下我仍是更喜欢直接写表单而不是使用symfony内置的表单对象来穿件表单,但当我一个表单比较重要,须要csrf保护的时候 我会选择使用这种方法来表单。php
官方文档有介绍一大堆经过类建立表单这里我就不想在这块多说。只为直接快速使用:html
使用一个无底层类表单:
web
<?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保护。post
大部分工做是由form_row帮助方法类完成的,它默认在一个div中为每一个字段渲染显示标签,错误信息和HTML表单部件。
注意,你能够经过form.vars.value 来访问你当前是表当数据:ui
{{ form.vars.value.task }}
手工渲染每个表单字段
form_row帮助器能让你很快的渲染你表单中的每个字段,而且每一行能够被自定义化。可是生活不老是那么简单的,你也可能要手动的渲染每个字段。
Twig格式:this
{{ 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选项是可选的,但为不一样的表单生成不一样的令牌极大的增强了安全性。