正常狀況下我仍是更喜歡直接寫表單而不是使用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選項是可選的,但爲不一樣的表單生成不一樣的令牌極大的增強了安全性。