鍍金池/ 教程/ PHP/ 如何自定義表單渲染
如何以非繼承方式自定義方法
如何創(chuàng)建事件監(jiān)聽器
如何以非繼承方式擴(kuò)展一個類
如何記錄消息到不同的文件
如何掌握并創(chuàng)建新的環(huán)境
如何使用 Doctrine DBAL
"XXX is deprecated" E-USER-DEPRECATED 的警告是什么意思?
在登錄表單中使用 CSRF 保護(hù)
如何注冊自定義 DQL 函數(shù)
如何為表單類配置空數(shù)據(jù)
如何嵌入集合表單
如何創(chuàng)建自定義認(rèn)證提供者
如何使用 Apache Router
如何組織配置文件
部署在 Microsoft Azure 云
如何在路由參數(shù)中允許"/"字符
如何在安全,路由,服務(wù)和驗證中使用表達(dá)式
如何對顯示控制臺信息配置 Monolog
如何為一個 Bundle 創(chuàng)建友好的配置
如何改變默認(rèn)的目標(biāo)路徑行為
如何在運行測試之前自定義引導(dǎo)過程
如何從路由向控制器傳輸額外的信息
如何從數(shù)據(jù)庫(實體提供者)讀取安全用戶
如何從 Controller 調(diào)用一個命令
如何創(chuàng)建自定義表單密碼驗證器
如何使用內(nèi)建的 PHP Web 服務(wù)器
如何在功能測試中用 Token 模擬認(rèn)證
配置 Session 文件的保存目錄
理解前端控制器、內(nèi)核及環(huán)境如何協(xié)同工作
如何實現(xiàn)一個簡單的注冊表單
如何使用 Doctrine 擴(kuò)展:Timestampable, Sluggable, Translatable 等等
如何使用多個實體管理器和連接
如何自定義表單渲染
如何安裝第三方 Bundles
使用預(yù)認(rèn)證安全防火墻
如何簡化多個 Bundle 的配置
會話代理實例
安裝 Composer
如何冒充一個用戶
如何注冊一個新的請求格式和 MIME 類型
如何在功能測試中使用分析器
如何在服務(wù)容器內(nèi)設(shè)置外部參數(shù)
如何重寫 Symfony 默認(rèn)的目錄結(jié)構(gòu)
如何在一個 Symfony 控制器中創(chuàng)建一個 SOAP 的 Web 服務(wù)
如何使用序列化
部署在 Platform.sh
升級一個副版本
如何寫一個自定義的 Twig 擴(kuò)展
如何在 SubVersion 中創(chuàng)建并保存一個 Symfony 項目
使用 PHP 庫聯(lián)合,編譯和最小化 Web 資產(chǎn)
如何創(chuàng)建一個自定義的數(shù)據(jù)收集器
如何使用和注冊命名空間路徑
如何使用 Monolog 記錄日志
如何建立一個傳統(tǒng)的登錄表單
如何強(qiáng)制路由總是使用 HTTPS 或者 HTTP
如何在模板中使用 PHP 而不是 Twig
如何動態(tài)選擇密碼加密算法
避免匿名用戶開始 Session 會話
如何測試 Doctrine 倉庫
如何在功能測試中測試一封電子郵件被發(fā)送
Symfony2 與 Symfony1 的區(qū)別
使用結(jié)尾反斜線重定向 URL
(configuration)如何在數(shù)據(jù)庫中使用 PdoSessionHandler 存儲 Sessions
如何使用匹配器有條件地啟用分析器
部署在 Heroku 云
如何不用自定義控制器配置重定向
如何在 Bundle 內(nèi)部加載服務(wù)配置
如何處理不同的錯誤級別
如何在應(yīng)用中保護(hù)服務(wù)和方法
如何對表單單元測試
如何把命令定義為服務(wù)
如何配置 Monolog 從日志中排除 404 錯誤
如何使用控制臺
如何測試與數(shù)據(jù)庫交互的代碼
如何在路由中使用除了 GET 和 POST 的 HTTP 方法
如何使用云服務(wù)發(fā)送電子郵件
如何創(chuàng)建一個控制臺命令
在遺留的應(yīng)用上使用 Symfony Session
如何使用高級的訪問控制列表
如何不用一個自定義的控制器渲染一個模板
如何重寫部分 Bundle
升級一個主版本
安全訪問控制是如何工作的
如何使用 Bundle 的繼承來重寫部分 Bundle
如何使用 Voter 檢查用戶權(quán)限
如何為多個 Doctrine 的實現(xiàn)提供模型類
如何使用作用域
如何部署一個 Symfony 應(yīng)用
如何用 "inherit-data" 減少代碼冗余
如何注冊事件監(jiān)聽器和訂閱
使用 Bower 安裝 Symfony
如何創(chuàng)建一個自定義路由加載器
如何創(chuàng)建一個自定義的驗證限制
在獨立注入類中使用參數(shù)
如何使用 Assetic 和 Twig Functions 進(jìn)行圖像優(yōu)化
如何利用表單事件動態(tài)修改表單
如何在過濾器的前后設(shè)置事件分發(fā)器
如何在 Bundle 中使用 Compiler Passes
緩存包含 CSRF 保護(hù)表單的頁面
如何注入變量到所有的模板(如全局變量)
如何創(chuàng)建一個自定義表單域類型
如何限定防火墻使其只允許通過指定請求
如何把 Controller 定義為服務(wù)
如何使用 Gmail 發(fā)送郵件
升級一個補(bǔ)丁版本
如何創(chuàng)建一個表單類型擴(kuò)展
如何對不同的 URL 強(qiáng)制使用 HTTPS 或者 HTTP
如何使用 Varnish 加速我的 Web 站點
如何定義虛擬類和接口之間的關(guān)系
如何自定義登錄表單
如何測試多個客戶端的交互
PSR-7 Bridge
如何使用 YUI Compressor 裁剪 Javascripts 和 Stylesheets
在用戶的 Session 中使用局部 "Sticky"
如何定制錯誤頁
如何從已存在的數(shù)據(jù)庫中生成實體
如何用 Doctrine 上傳文件
可復(fù)用 Bundles 的最佳實踐
如何發(fā)送一封電子郵件
如何將 Assetic Filter 應(yīng)用到具體的文件擴(kuò)展名上
切換分析器存儲
如何上傳文件
限制 Session 元數(shù)據(jù)的寫入
如何使用多用戶提供者
如何使用數(shù)據(jù)轉(zhuǎn)換
配置一個 Web 服務(wù)器
如何編程訪問分析器數(shù)據(jù)
如何在路由中使用服務(wù)容器參數(shù)
如何在控制臺生成 URL 和發(fā)送郵件
如何將你的開發(fā)環(huán)境優(yōu)化為調(diào)試環(huán)境
如何在控制臺命令中啟用日志
如何在功能測試中模擬 HTTP 認(rèn)證
如何使用 API 驗證用戶
如何移除 AcmeDemoBundle
控制臺命令
如何配置 Symfony 使其工作在負(fù)載均衡和反轉(zhuǎn)代理
如何添加“記住我”登錄功能
如何使用 Assetic 進(jìn)行資產(chǎn)管理
如何限定防火墻使其接受指定主機(jī)
如何使用訪問控制列表(ACLs)
如何裁剪 CSS/JS 文件(使用 UglifyJS 和 UglifyCSS)
如何緩存電子郵件
如何使用 submit() 函數(shù)處理表單提交
如何在 Git 中創(chuàng)建并保存一個 Symfony 項目
如何創(chuàng)建自定義用戶提供者
如何對電子郵件錯誤配置 Monolog
如何在開發(fā)時使用電子郵件

如何自定義表單渲染

Symfony 提供了很多種來渲染表單的方法。在本指導(dǎo)中,你將學(xué)習(xí)如何自定義你的表單的每一個可能的部分使用盡可能少的步驟,不論你在你的模板引擎中使用的是 Twig 還是 PHP。

表單渲染基礎(chǔ)

召回表單區(qū)域的標(biāo)簽,錯誤以及 HTML 插件可以很容易地通過使用 Twig 的 form_row 功能或者 PHP 的幫助方法來進(jìn)行渲染:

Twig:

{{ form_row(form.age) }}

PHP:

<?php echo $view['form']->row($form['age']); ?>

你也可以分別渲染這三個部分:

Twig:

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

PHP:

<div>
    <?php echo $view['form']->label($form['age']); ?>
    <?php echo $view['form']->errors($form['age']); ?>
    <?php echo $view['form']->widget($form['age']); ?>
</div>

在這兩種情況下,表單的標(biāo)簽,錯誤以及 HTML 插件通過使用一系列的 Symfony 包含的標(biāo)記進(jìn)行了渲染。舉例來說,上述兩個模板都會被渲染:

<div>
    <label for="form_age">Age</label>
    <ul>
        <li>This field is required</li>
    </ul>
    <input type="number" id="form_age" name="form[age]" />
</div>

為了快速使用原型并且測試表單,你可以只使用一行來渲染整個表單:

Twig:

{# renders all fields #}
{{ form_widget(form) }}

{# renders all fields *and* the form start and end tags #}
{{ form(form) }}

PHP:

<!-- renders all fields -->
<?php echo $view['form']->widget($form) ?>

<!-- renders all fields *and* the form start and end tags -->
<?php echo $view['form']->form($form) ?>

本指導(dǎo)接下來的部分將解釋表單的每一部分的標(biāo)記如何在幾個不同的程度來調(diào)整。獲取更多關(guān)于表單渲染的一般信息詳見在模板中渲染表單。

什么是表單的主題?

Symfony 使用表單碎片——一小塊模板用來渲染一小塊表單——來渲染表單的每一部分——區(qū)域標(biāo)簽,錯誤,輸入文本框,選擇標(biāo)簽等等。

這個碎片在 Twig 中被定義為區(qū)域,同時在 PHP 中被定義為模板文件。

主題只不過是一些碎片的集合,這些碎片就是你在渲染表單時想要使用的。換句話說,如果你想要個性化一部分表單是如何被渲染的,你需要輸入一個主題,這個主題包含了適合的個性化的表單碎片。

Symfony 中包含四個內(nèi)建的表單主題這些主題定義了需要渲染的表單的每一個部分的每一個碎片:

當(dāng)你使用 Bootstrap 表單主題并且手動渲染表單時,對字段調(diào)用 form_label() 并不會意味著什么。這是因為 Bootstrap 內(nèi)部,標(biāo)簽已經(jīng)在 form_widget() 中顯示。

在下一節(jié)中,你將學(xué)習(xí)到通過重寫或者部分重寫它的碎片如何個性化主題。

舉例來說,當(dāng)整型字段的控件被渲染時,input number 字段就會產(chǎn)生:

Twig:

{{ form_widget(form.age) }}

PHP:

<?php echo $view['form']->widget($form['age']) ?>

渲染:

<input type="number" id="form_age" name="form[age]" required="required" value="33" />

內(nèi)部的,Symfony 使用 integer_widget 碎片來渲染字段。這是因為字段類型是整型并且你正在渲染它的控件(這個和它的標(biāo)簽或者錯誤截然相反)。

在 Twig 中這個將會從 form_div_layout.html.twig 模板中默認(rèn)到 integer_widget 區(qū)域。

在 PHP 中將會是位于 FrameworkBundle/Resources/views/Form 文件夾的 integer_widget.html.php 文件。

默認(rèn)的 integer_widget 的安裝啟用如下所示:

Twig:

{# form_div_layout.html.twig #}
{% block integer_widget %}
    {% set type = type|default('number') %}
    {{ block('form_widget_simple') }}
{% endblock integer_widget %}

PHP:

<!-- integer_widget.html.php -->
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : "number")) ?>

正如你所見,這個碎片自己渲染另一個碎片——form_widget_simple

Twig:

{# form_div_layout.html.twig #}
{% block form_widget_simple %}
    {% set type = type|default('text') %}
    <input type="{{ type }}" {{ block('widget_attributes') }} {% if value is not empty %}value="{{ value }}" {% endif %}/>
{% endblock form_widget_simple %}

PHP:

<!-- FrameworkBundle/Resources/views/Form/form_widget_simple.html.php -->
<input
    type="<?php echo isset($type) ? $view->escape($type) : 'text' ?>"
    <?php if (!empty($value)): ?>value="<?php echo $view->escape($value) ?>"<?php endif ?>
    <?php echo $view['form']->block($form, 'widget_attributes') ?>
/>

重點是,碎片指示了表單的每一個部分的 HTML 輸出。為了個性化表單輸出,你只需要識別并且重寫正確的碎片。一系列的表單碎片的結(jié)合就是大家所熟知的表單“主題”。當(dāng)渲染表單的時候,你可以選擇應(yīng)用哪個或者哪些主題。

在 Twig 中主題是簡單的模板文件并且碎片是定義在這些文件中的區(qū)域。

在 PHP 中主題是一個文件夾并且碎片是這個文件夾中的獨立的模板文件。

識別哪個區(qū)域來個性化
在本例中,個性化的碎片名為 integer_widget,因為你想要為所有的整型字段類型重寫 HTML 控件,如果你需要個性化 textarea 字段,你就要個性化 textarea_widget

正如你所見,碎片的名稱是由字段類型以及字段的哪一個部分(例如 widget, label, errors, row)被渲染組合而成的。同樣的,為了個性化錯誤如何僅使用輸入文本字段渲染,你需要個性化 text_errors 碎片。

然而,更常見的是你想要個性化所有的字段的錯誤顯示方式。你可以通過個性化 form_errors 碎片來達(dá)到這個目的。利用字段類型繼承的優(yōu)點。特別的,由于文本類型是由表單類型擴(kuò)展而來的,在回到它的父碎片名稱之前如果它不存在(例如 form_errors),表單的組件將會首先尋找特定類型的碎片(例如 text_errors)。

獲取有關(guān)這個話題的更多信息,參見表單碎片命名

表單主題化

為了看看表單主題化的威力,假設(shè)你想要將每一個輸入數(shù)字字段捆綁一個 div 標(biāo)簽。做這個的關(guān)鍵就是將 integer_widget 碎片個性化。

在 Twig 中進(jìn)行表單主題化

當(dāng)在 Twig 中個性化表單字段區(qū)域時,在個性化的表單區(qū)域可能存在的地方你有兩種選擇:

方法 優(yōu)點 缺點
將相同的模板作為表單插入 快速簡單 不能在其它的模板中應(yīng)用
插入單獨分開的模板 可以在很多模板中重復(fù)使用 需要創(chuàng)建額外的模板

這兩種方法都會產(chǎn)生相同的結(jié)果但是在不同的情況下各有各的優(yōu)點。

方法 1:將相同的模板作為表單插入

最簡單的個性化 integer_widget 區(qū)域的方法是直接在實際渲染表單的模板中進(jìn)行。

{% extends '::base.html.twig' %}

{% form_theme form _self %}

{% block integer_widget %}
    <div class="integer_widget">
        {% set type = type|default('number') %}
        {{ block('form_widget_simple') }}
    </div>
{% endblock %}

{% block content %}
    {# ... render the form #}

    {{ form_row(form.age) }}
{% endblock %}

通過使用特殊的 {% form_theme form _self %} 標(biāo)簽,Twig 在相同的模板中尋找任何重寫的表單區(qū)域。假設(shè) form.age 區(qū)域是整型類型的字段,當(dāng)它的控件被渲染時,個性化的 integer_widget 區(qū)域?qū)皇褂谩?

這個方法的缺點就是個性化的表單區(qū)域當(dāng)在其它的模板中渲染其它表單時不能重復(fù)利用。換句話說,這個方法在當(dāng)對你的應(yīng)用程序中的單一的表單進(jìn)行表單個性化時最有用。如果你想在你的應(yīng)用程序的多個(或者所有)表單中重復(fù)利用表單個性化,那么請閱讀下一節(jié)。

方法 2:插入分開的模板

你也可以選擇將個性化的 integer_widget 模板區(qū)域放置于完全分開的模板中。代碼以及最終結(jié)果是一樣的,但是你現(xiàn)在可以重復(fù)在多個模板中使用表單個性化:

{# app/Resources/views/Form/fields.html.twig #}
{% block integer_widget %}
    <div class="integer_widget">
        {% set type = type|default('number') %}
        {{ block('form_widget_simple') }}
    </div>
{% endblock %}

既然你已經(jīng)創(chuàng)建了個性化的表單區(qū)域,那么你就需要告訴 Symfony 來使用它。在你實際渲染表單的地方插入模板,通過 form_theme 標(biāo)簽告訴 Symfony 來使用它:

{% form_theme form 'AppBundle:Form:fields.html.twig' %}

{{ form_widget(form.age) }}

當(dāng) form.age 標(biāo)簽被渲染的時候,Symfony 將會從新的模板中使用 integer_widget 區(qū)域同時 input 標(biāo)簽將會被捆綁在個性化區(qū)域的特定的 div 元素上。

多重模板

一個表單可以通過應(yīng)用多個模板來進(jìn)行個性化。為了完成這個,需要使用 with 關(guān)鍵字將所有模板的名稱作為一個數(shù)組傳遞:

{% form_theme form with ['::common.html.twig', ':Form:fields.html.twig',
                         'AppBundle:Form:fields.html.twig'] %}

{# ... #}

模板可以位于不同的 bundle 同時它們甚至可以儲存在全局目錄 app/Resources/views/ 中。

子表單

你也可以應(yīng)用表單主題來區(qū)分你的子表單:

{% form_theme form.child 'AppBundle:Form:fields.html.twig' %}

當(dāng)你想要為不同于你的主表單的嵌套的表單定制主題時這個就會很有用。只要區(qū)分你的主題就好:

{% form_theme form 'AppBundle:Form:fields.html.twig' %}

{% form_theme form.child 'AppBundle:Form:fields_child.html.twig' %}

PHP 環(huán)境下的表單主題化

當(dāng)你使用 PHP 作為模板引擎的時候,個性化碎片的唯一方法就是創(chuàng)建一個新的模板文件——這個和使用 Twig 的第二種方法很相似。

模板文件必須在碎片之后命名。你必須創(chuàng)建一個 integer_widget.html.php 文件從而能個性化 integer_widget 碎片。

<!-- app/Resources/views/Form/integer_widget.html.php -->
<div class="integer_widget">
    <?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : "number")) ?>
</div>

既然你已經(jīng)創(chuàng)建了個性化的表單模板,那么你就需要告訴 Symfony 來使用它。在你實際渲染表單的地方插入模板,通過 setTheme 幫助方法告訴 Symfony 來使用它:

<?php $view['form']->setTheme($form, array('AppBundle:Form')); ?>

<?php $view['form']->widget($form['age']) ?>

當(dāng) form.age 標(biāo)簽被渲染的時候,Symfony 將會使用個性化的 integer_widget.html.php 模板,同時 input 標(biāo)簽將會被捆綁在 div 元素上。

如果你想要將主題應(yīng)用到特定的子表單上,將它傳遞給 setTheme 方法:

<?php $view['form']->setTheme($form['child'], 'AppBundle:Form/Child'); ?>

引用基本表單區(qū)域(只對 Twig 有效)

目前為止,重寫特定的表單區(qū)域最好的方法就是從 form_div_layout.html.twig 復(fù)制默認(rèn)的區(qū)域,然后將它粘貼到不同的模板中,然后將它個性化。在很多情況下,你可以通過在個性化時引用基本表單區(qū)域來避免這一步。

這個很容易做,但是如果你的表單區(qū)域作為表單位于同一個模板或者分開的模板中就會有輕微的不一樣。

從作為表單的相同模板的內(nèi)部引用區(qū)域

通過添加 use 標(biāo)簽的方式來在你渲染表單的地方輸入:

{% use 'form_div_layout.html.twig' with integer_widget as base_integer_widget %}

現(xiàn)在,當(dāng)從 form_div_layout.html.twig 中來的區(qū)域被輸入后,integer_widget 區(qū)域被叫做 base_integer_widget。這就意味著當(dāng)你重新定義 integer_widget 區(qū)域你可以通過 base_integer_widget 引用默認(rèn)的標(biāo)記:

{% block integer_widget %}
    <div class="integer_widget">
        {{ block('base_integer_widget') }}
    </div>
{% endblock %}

從外部模板引用基本區(qū)域

如果你的表單個性化位于外部模板,你可以通過使用 Twig 的 parent() 功能來引用基本區(qū)域:

{# app/Resources/views/Form/fields.html.twig #}
{% extends 'form_div_layout.html.twig' %}

{% block integer_widget %}
    <div class="integer_widget">
        {{ parent() }}
    </div>
{% endblock %}

當(dāng)使用 PHP 作為模板引擎的時候?qū)⒉豢赡芤没緟^(qū)域。你必須手動復(fù)制基本區(qū)域的內(nèi)容到你的新模板文件中。

應(yīng)用程序范圍內(nèi)的自定義

如果你想要將特定的個性化全局應(yīng)用到你的應(yīng)用程序之中,你可以通過將表單的個性化放到外部模板然后將它輸入到你的應(yīng)用程序配置之中。

Twig

通過使用下列的配置,任何在 AppBundle:Form:fields.html.twig 模板中的自定義表單區(qū)域當(dāng)表單被渲染時都會被全局使用。

YAML:

# app/config/config.yml
twig:
    form_themes:
        - 'AppBundle:Form:fields.html.twig'
    # ...

XML:

<!-- app/config/config.xml -->
<twig:config>
    <twig:form-theme>AppBundle:Form:fields.html.twig</twig:form-theme>
    <!-- ... -->
</twig:config>

PHP:

// app/config/config.php
$container->loadFromExtension('twig', array(
    'form_themes' => array(
        'AppBundle:Form:fields.html.twig',
    ),

    // ...
));

默認(rèn)情況下,當(dāng)渲染表單時 Twig 使用 div 布局。然而,有些人可能更喜歡使用 table 渲染表單。使用 form_table_layout.html.twig 資源來調(diào)用這樣的布局:

YAML:

# app/config/config.yml
twig:
    form_themes:
        - 'form_table_layout.html.twig'
    # ...

XML:

<!-- app/config/config.xml -->
<twig:config>
    <twig:form-theme>form_table_layout.html.twig</twig:form-theme>
    <!-- ... -->
</twig:config>

PHP:

// app/config/config.php
$container->loadFromExtension('twig', array(
    'form_themes' => array(
        'form_table_layout.html.twig',
    ),

    // ...
));

如果你只是想用在一個模板中有更改,在你的模板中添加下列這一行代碼而不是將模板添加成資源:

{% form_theme form 'form_table_layout.html.twig' %}

注意 form 變量在上述的代碼中是你傳遞到你的模板表單視圖變量。

PHP

通過使用下列配置,任何在 app/Resources/views/Form 文件夾下的表單的自定義的碎片在渲染表單時將會被全局應(yīng)用。

YAML:

# app/config/config.yml
framework:
    templating:
        form:
            resources:
                - 'AppBundle:Form'
    # ...

XML:

<!-- app/config/config.xml -->
<framework:config>
    <framework:templating>
        <framework:form>
            <resource>AppBundle:Form</resource>
        </framework:form>
    </framework:templating>
    <!-- ... -->
</framework:config>

PHP:

// app/config/config.php
// PHP
$container->loadFromExtension('framework', array(
    'templating' => array(
        'form' => array(
            'resources' => array(
                'AppBundle:Form',
            ),
        ),
     ),

     // ...
));

默認(rèn)情況下,當(dāng)渲染表單時 PHP 使用 div 布局。然而,有些人可能更喜歡使用 table 渲染表單。使用 FrameworkBundle:FormTable 資源來調(diào)用這樣的布局:

YAML:

# app/config/config.yml
framework:
    templating:
        form:
            resources:
                - 'FrameworkBundle:FormTable'

XML:

<!-- app/config/config.xml -->
<framework:config>
    <framework:templating>
        <framework:form>
            <resource>FrameworkBundle:FormTable</resource>
        </framework:form>
    </framework:templating>
    <!-- ... -->
</framework:config>

PHP:

// app/config/config.php
$container->loadFromExtension('framework', array(
    'templating' => array(
        'form' => array(
            'resources' => array(
                'FrameworkBundle:FormTable',
            ),
        ),
    ),

     // ...
));

如果你只是想要在一個模板中有更改,在你的模板中添加下列這一行代碼而不是將模板添加成資源:

<?php $view['form']->setTheme($form, array('FrameworkBundle:FormTable')); ?>

注意 $form 變量在上述的代碼中是你傳遞到你的模板表單視圖變量。

如何在獨立的字段中進(jìn)行自定義

目前為止,你已經(jīng)看到了不同的方式來自定義所有的文本字段類型的控件輸出。你也可以自定義獨立的字段。舉例來說,假設(shè)你在 product 表單中有兩個文本字段——namedescription——但是你只想自定義其中的一個。這個可以通過自定義名為區(qū)域的代碼屬性以及需要自定義的部分名稱的組合碎片來完成。舉例來說,只自定義 name 字段:

{% form_theme form _self %}

{% block _product_name_widget %}
    <div class="text_widget">
        {{ block('form_widget_simple') }}
    </div>
{% endblock %}

{{ form_widget(form.name) }}
<!-- Main template -->
<?php echo $view['form']->setTheme($form, array('AppBundle:Form')); ?>

<?php echo $view['form']->widget($form['name']); ?>

<!-- app/Resources/views/Form/_product_name_widget.html.php -->
<div class="text_widget">
      echo $view['form']->block('form_widget_simple') ?>
</div>

在這里,_product_name_widget 碎片定義了模板使用編號為 product_name 的字段(名稱是 product[name])。

字段的 product 屬性是表單的名稱,這個可能是手動設(shè)置的或者是基于你的表單類型名稱自動產(chǎn)生的(例如 ProductType 等同于 product)。如果你不確定你的表單的名稱,就需要你的表單名稱產(chǎn)生的源。

如果你想要改變 _product_name_widget 區(qū)域的 product 或者 name 屬性你可以在你的表單中設(shè)置 block_name 選項:


use Symfony\Component\Form\FormBuilderInterface;

public function buildForm(FormBuilderInterface $builder, array $options) { // ...

$builder->add('name', 'text', array(
    'block_name' => 'custom_name',
));

}



然后區(qū)域的名稱就會變成 **_product_custom_name_widget**。

你也可以使用相同的方法來重寫整個字段行:

Twig:

{% form_theme form _self %}

{% block _product_name_row %}
    <div class="name_row">
        {{ form_label(form) }}
        {{ form_errors(form) }}
        {{ form_widget(form) }}
    </div>
{% endblock %}

{{ form_row(form.name) }}

PHP:

<!-- Main template -->
<?php echo $view['form']->setTheme($form, array('AppBundle:Form')); ?>

<?php echo $view['form']->row($form['name']); ?>

<!-- app/Resources/views/Form/_product_name_row.html.php -->
<div class="name_row">
    <?php echo $view['form']->label($form) ?>
    <?php echo $view['form']->errors($form) ?>
    <?php echo $view['form']->widget($form) ?>
</div>

其它一些自定義

目前為止,本指導(dǎo)已經(jīng)介紹過一些如何渲染表單的不同的個性化方法。關(guān)鍵就是要個性化特定的碎片,這個碎片和你想要控制的表單的屬性相關(guān)。(詳見命名表單區(qū)域

在下一節(jié)中,你將學(xué)習(xí)如何使幾個普通的表單個性化。為了這些個性化,需要使用表單主題化一節(jié)中介紹的方法。

個性化錯誤輸出

表單的組件只是會處理校驗錯誤如何被渲染而不是實際的校驗信息。這些錯誤信息由你應(yīng)用到你的對象的校驗限制自己決定。獲取更多信息詳見校驗章節(jié)。

當(dāng)表單提交錯誤的時候有很多很多不同的方式來決定錯誤如何被渲染。當(dāng)你使用 form_errors 的時候字段的錯誤信息就會被渲染:

Twig:

{{ form_errors(form.age) }}

PHP:

<?php echo $view['form']->errors($form['age']); ?>

默認(rèn)情況下,錯誤在一個沒有排序的列表中被渲染:

<ul>
    <li>This field is required</li>
</ul>

為了重寫所有文件的錯誤如何被渲染,簡單的復(fù)制粘貼并且個性化 form_errors 碎片就好。

Twig:

{# form_errors.html.twig #}
{% block form_errors %}
    {% spaceless %}
        {% if errors|length > 0 %}
        <ul>
            {% for error in errors %}
                <li>{{ error.message }}</li>
            {% endfor %}
        </ul>
        {% endif %}
    {% endspaceless %}
{% endblock form_errors %}

PHP:

<!-- form_errors.html.php -->
<?php if ($errors): ?>
    <ul>
        <?php foreach ($errors as $error): ?>
            <li><?php echo $error->getMessage() ?></li>
        <?php endforeach ?>
    </ul>
<?php endif ?>

如何應(yīng)用這些個性化參見表單主題化。

你也可以自定義這些錯誤輸出成為一種特定的字段類型。為了只是個性化這些錯誤使用的標(biāo)志,遵循和上面相同的步驟但是把內(nèi)容放到相關(guān)的 _errors 區(qū)域(或者文件以防是 PHP 模板)。舉例來說,text_errors (或者 text_errors.html.php)。

找出哪個是你必須個性化的區(qū)域或者文件詳見表單碎片命名。

對于你的表單來說是全局的特定的錯誤(例如不僅僅是一個字段)被分開來渲染。通常在你的表單的頂部:

Twig:

{{ form_errors(form) }}

PHP:

<?php echo $view['form']->render($form); ?>

為了僅僅個性化這些錯誤所使用的標(biāo)記,遵循上述所說的步驟,但是檢查 compound 的值是否設(shè)置為。如果為的話,這就意味著現(xiàn)在正在被渲染的就是字段的集合(例如整個表單),并且不僅僅是一個獨立的字段。

Twig:

{# form_errors.html.twig #}
{% block form_errors %}
    {% spaceless %}
        {% if errors|length > 0 %}
            {% if compound %}
                <ul>
                    {% for error in errors %}
                        <li>{{ error.message }}</li>
                    {% endfor %}
                </ul>
            {% else %}
                {# ... display the errors for a single field #}
            {% endif %}
        {% endif %}
    {% endspaceless %}
{% endblock form_errors %}

PHP:

<!-- form_errors.html.php -->
<?php if ($errors): ?>
    <?php if ($compound): ?>
        <ul>
            <?php foreach ($errors as $error): ?>
                <li><?php echo $error->getMessage() ?></li>
            <?php endforeach ?>
        </ul>
    <?php else: ?>
        <!-- ... render the errors for a single field -->
    <?php endif ?>
<?php endif ?>

個性化“表單行”

當(dāng)你可以管理的時候,最簡單的渲染表單的字段的方法就是通過 form_row 功能,這個功能渲染標(biāo)簽,錯誤以及字段的 HTML 插件。為了個性化渲染所有表單字段行所使用的標(biāo)志,重寫 form_row 碎片。舉例來說,你想要在每一個行的周圍的 div 元素中添加一個類:

Twig:

{# form_row.html.twig #}
{% block form_row %}
    <div class="form_row">
        {{ form_label(form) }}
        {{ form_errors(form) }}
        {{ form_widget(form) }}
    </div>
{% endblock form_row %}

PHP:

<!-- form_row.html.php -->
<div class="form_row">
    <?php echo $view['form']->label($form) ?>
    <?php echo $view['form']->errors($form) ?>
    <?php echo $view['form']->widget($form) ?>
</div>

如何應(yīng)用這些個性化詳見表單主題化。

為字段標(biāo)簽添加必填星號標(biāo)注

如果你想要將你的所有的必填字段加上必填星號標(biāo)注(*),你可以通過個性化 form_label 碎片來完成。

在 Twig 中,如果你正在你的表單的相同的模板中個性化表單,修正 use 標(biāo)簽并且添加下列代碼:

{% use 'form_div_layout.html.twig' with form_label as base_form_label %}

{% block form_label %}
    {{ block('base_form_label') }}

    {% if required %}
        <span class="required" title="This field is required">*</span>
    {% endif %}
{% endblock %}

在 Twig 中,如果你正在你的表單的不同的模板中個性化表單,使用下列代碼:

{% extends 'form_div_layout.html.twig' %}

{% block form_label %}
    {{ parent() }}

    {% if required %}
        <span class="required" title="This field is required">*</span>
    {% endif %}
{% endblock %}

當(dāng)使用 PHP 作為模板引擎時你必須從原始模板中復(fù)制內(nèi)容:

<!-- form_label.html.php -->

<!-- original content -->
<?php if ($required) { $label_attr['class'] = trim((isset($label_attr['class']) ? $label_attr['class'] : '').' required'); } ?>
<?php if (!$compound) { $label_attr['for'] = $id; } ?>
<?php if (!$label) { $label = $view['form']->humanize($name); } ?>
<label <?php foreach ($label_attr as $k => $v) { printf('%s="%s" ', $view->escape($k), $view->escape($v)); } ?>><?php echo $view->escape($view['translator']->trans($label, array(), $translation_domain)) ?></label>

<!-- customization -->
<?php if ($required) : ?>
    <span class="required" title="This field is required">*</span>
<?php endif ?>

如何應(yīng)用這些個性化詳見表單主題化

僅使用 CSS

默認(rèn)情況下,請求字段的 label 標(biāo)簽被一個叫做 required CSS 類渲染。因此,你也可以只使用 CSS 來添加星號標(biāo)注:

label.required:before {
content: "* ";
}

添加“幫助”消息

你也可以自定義你的表單控件從而擁有“幫助”信息選項。

在 Twig 中,如果你正在你的表單的相同的模板中個性化表單,修正 use 標(biāo)簽并且添加下列代碼:

{% use 'form_div_layout.html.twig' with form_widget_simple as base_form_widget_simple %}

{% block form_widget_simple %}
    {{ block('base_form_widget_simple') }}

    {% if help is defined %}
        <span class="help">{{ help }}</span>
    {% endif %}
{% endblock %}

在 Twig 中,如果你正在你的表單的不同的模板中個性化表單,使用下列代碼:

{% extends 'form_div_layout.html.twig' %}

{% block form_widget_simple %}
    {{ parent() }}

    {% if help is defined %}
        <span class="help">{{ help }}</span>
    {% endif %}
{% endblock %}

當(dāng)使用 PHP 作為模板引擎時你必須從原始模板中復(fù)制內(nèi)容:

<!-- form_widget_simple.html.php -->

<!-- Original content -->
<input
    type="<?php echo isset($type) ? $view->escape($type) : 'text' ?>"
    <?php if (!empty($value)): ?>value="<?php echo $view->escape($value) ?>"<?php endif ?>
    <?php echo $view['form']->block($form, 'widget_attributes') ?>
/>

<!-- Customization -->
<?php if (isset($help)) : ?>
    <span class="help"><?php echo $view->escape($help) ?></span>
<?php endif ?>

為了渲染字段下的幫助信息,傳遞一個 help 變量:

Twig:

{{ form_widget(form.title, {'help': 'foobar'}) }}

PHP:

<?php echo $view['form']->widget($form['title'], array('help' => 'foobar')) ?>

如何應(yīng)用這些個性化詳見表單主題化。

使用表單變量

渲染表單的不同部分的大多數(shù)功能(例如表單控件,表單標(biāo)簽,表單錯誤等等)都可以允許你直接做特定的自定義??聪旅孢@個例子:

Twig:

{# render a widget, but add a "foo" class to it #}
{{ form_widget(form.name, { 'attr': {'class': 'foo'} }) }}

PHP:

<!-- render a widget, but add a "foo" class to it -->
<?php echo $view['form']->widget($form['name'], array(
    'attr' => array(
        'class' => 'foo',
    ),
)) ?>

這個包含表單“變量”的數(shù)組作為第二個參數(shù)傳遞。更多關(guān)于這方面的細(xì)節(jié),詳見更多關(guān)于表單變量。