如何自定义表单渲染

2.8 版本
维护中的版本

Symfony提供了很多种来渲染表单的方法。在本章中,你将学习如何自定义你的表单的每一个可能的部分,使用尽可能少的步骤,无论你在你的模板引擎中使用的是 Twig 还是 PHP。

---基础的表单渲染---

回忆一下,你可以很容易的使用form_row的Twig函数和php助手函数row方法渲染表单字段的label,错误提示以及 HTML控件。

1
{{ form_row(form.age) }}
1
<?php echo $view['form']->row($form['age']); ?>

你也可以分别渲染字段的三个部分:

1
2
3
4
5
<div>
    {{ form_label(form.age) }}
    {{ form_errors(form.age) }}
    {{ form_widget(form.age) }}
</div>
1
2
3
4
5
<div>
    <?php echo $view['form']->label($form['age']); ?>
    <?php echo $view['form']->errors($form['age']); ?>
    <?php echo $view['form']->widget($form['age']); ?>
</div>

这两个例子,通过symofny标记来渲染表单的label,错误提示和HTML控件。上面的模板会呈现如下效果:

1
2
3
4
5
6
7
<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>

还有更快方式来呈现原型或者一个测试表单,只需要要一样代码就可以渲染整个表单:

1
2
3
4
5
{# renders all fields #}
{{ form_widget(form) }}
 
{# renders all fields *and* the form start and end tags #}
{{ form(form) }}
1
2
3
4
5
<!-- 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) ?>

剩下的部分将解释表单的每一个标记的不同修改程度。关于更多表单渲染的知识,请阅读:如何去控制表单渲染

---什么是表单主题?---

Symfony使用表单片段 - 一个小块模板渲染表单的一部分 - 每一个小模板渲染每一个表单部分 - 字段label,字段错误信息,inpput文本字段,select 标签,等。

这些片段在 Twig 中被定义为区域,同时在 PHP 中被定义为模板文件。

一个主题只不过就是渲染表单时的一组片段的集合。换句话说,如果你想自定义一部分表单渲染,你需要导入一个主题,这个主题包含了个性化的表单片段。

Symfony​​带有一些内置的表单主题,这个主题定义了需要渲染表单的每一个部分:

Caution

当你使用Bootstrap表单主题并手动渲染字段时,调用checkbox/radio字段的form_label()没有显示任何东西。这是由于Bootstrap内部,label已经通过form_widget()显示。

下一章你将学习如何自定义主题,通过重写(一些或者全部的)片段。

例如,当integer字段类型的控件被渲染时,一个inputnumber字段就会生成:

1
{{ form_widget(form.age) }}
1
<?php echo $view['form']->widget($form['age']) ?>

渲染:

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

在内部,symfony使用integer_widget片段去渲染字段。这是因为这个字段的类型是integer,并且你也渲染了他的控件(有label和errors)。

这个就是从twig中的默认 form_div_layout.html.twig 模板的integer_widget块中来。

在 PHP 中将会是位于 FrameworkBundle/Resources/views/Form 文件夹的 integer_widget.html.php 文件。

这个integer_widget片段的默认实现如下:

1
2
3
4
5
{# form_div_layout.html.twig #}
{% block integer_widget %}
    {% set type = type|default('number') %}
    {{ block('form_widget_simple') }}
{% endblock integer_widget %}
1
2
<!-- integer_widget.html.php -->
<?php echo $view['form']->block($form, 'form_widget_simple', array('type' => isset($type) ? $type : "number")) ?>

正如你看到的,这些片段自己也渲染其他的片段 - form_widget_simple

1
2
3
4
5
{# 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 %}
1
2
3
4
5
6
<!-- 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输出。为了定义表单的输出,你仅仅需要去识别并重写当前的片段。一组表单片段的集合就是大家所熟知的表单“主题”。当表单渲染时,你可以选择你想要使用的表单主题。

在Twig中一个主题是一个单独的模板文件并且这些片段定义在文件的block。

在php中一个主题是一个文件夹并且这些片段就是文件夹中的独立模板文件。

知道定制的块

在这个例子中,integer_widget是定制的块,因为你想去重写所有的intger字段类型的html widget(控件)。如果你需要去定制textarea字段,那么你需要去定制textarea_widget

integer 部分来自于类名:基于一个标准,IntegerType会成为integer

正如你所看到的,片段的名称是由字段类型组成,并且该字段会渲染的每一部分(如,widget, label, errors, row)。同理,如果你想去定制渲染文本框text字段的错误信息,你应该定制text_errors片段。

然而,更常见的是你想要个性化所有的字段的错误显示方式。你可以通过个性化 form_errors 片段来达到这个目的。这是利用字段类型继承的优点。具体来说,由于text类型是由form类型扩展而来的,在回到它的父片段名称之前如果它不存在(例如 form_errors),表单的组件将会首先寻找特定类型的片段(例如 text_errors)。

关于更多信息,请查看表单片段命名

---表单主题化---

看看表单主题化的威力,假设你想要在每个input number字段外包裹一个div标签。要做到这一点的关键是自定义integer_widget片段。

---在Twig中表单主题化---

当在twig中自定义表单字段块时,你有两个选择:

方法优点缺点
在同一模板内部自定义表单快速简单不能重用到其他模板
独立的模板内自定义表单可以在很多模板中重用需要创建额外的模板

这两种方法有相同的效果,但是在不同的情况下会有不同的效果。

---方法1:在同一模板内部自定义表单---1

自定义integer_widget块的最简单的方式是直接在要渲染的表单模板上定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% 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 %}标签,Twig在同一模板内部寻找复写的表单块。假设form.age字段是一个integer类型的字段,当他的部件被渲染时,这个自定义的integer_widget块将被使用。

这个方法的缺点是当在其他模板渲染表单时,自定义的表单块不能重用。换句话说,在你应用程序中的一个表单中使用自定义表单时,他是非常有用的。如果你想在多个表单中自定义一个能够重用的自定义表单,那么请你继续阅读。

---方法2:独立的模板内自定义表单---2

你可以选择把自定义的integer_widget表单块放到一个单独的模板中。代码以及最终的结果都是一样的,但是你现在可以在多个模板中使用表单自定义了:

1
2
3
4
5
6
7
{# 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 %}

现在您已经创建了自定义表单,你需要告诉Symfony使用它。在你实际渲染的表单模板内,通过form_theme标签告诉symfony使用这个模板。

1
2
3
{% form_theme form 'form/fields.html.twig' %}
 
{{ form_widget(form.age) }}

form.age被渲染时,symfony将使用新模板的integer_widget块并且这个input标签将包裹在自定义块指定的div元素中。

---多个模板---2|1

表单也可以通过多个模板来定制。要做到这一点,需要使用with关键字将所有模板名称作为一个数组传递:

1
2
3
{% form_theme form with ['common.html.twig', 'form/fields.html.twig'] %}
 
{# ... #}

这些模板可以位于不同的bundle中,使用函数名来引用这些模板,例如 AcmeFormExtraBundle:form:fields.html.twig

---子表单---2|2

你也可以应用表单主题来指定你的子表单:

1
{% form_theme form.child 'form/fields.html.twig' %}

当你想为一个主表单的子表单嵌入不同的自定义主题,这是非常有用的。只要区分你的主题就好了:

1
2
3
{% form_theme form 'form/fields.html.twig' %}
 
{% form_theme form.child 'form/fields_child.html.twig' %}

---PHP形式的表单主题化---

当使用php作为一个模板引擎时,唯一的方法就是去定义一个片段,然后去创建一个新的模板文件 - 这个和使用twig的第二种方式很相似。

模板文件必须以片段名命名。你必须创建一个integer_widget.html.php文件以便去定义integer_widget片段。

1
2
3
4
5
6
7
8
<!-- 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>

现在你已经创建了自定义的表单模板,你需要去告诉symofny来使用它。在你实际渲染表单的地方插入模板,通过 setTheme 帮助方法告诉 Symfony 来使用它:

1
2
3
<?php $view['form']->setTheme($form, array(':form')); ?>
 
<?php $view['form']->widget($form['age']) ?>

form.age被渲染时,Symfony将使用自定义的integer_widget.html.php模板并将input标签将包裹在div元素内。

如果你想把主题应用到特定的子表单上,那就传递它到setTheme方法:

1
<?php $view['form']->setTheme($form['child'], ':form'); ?>

Note

:form语法是基于模板的函数名:Bundle:Directory。这个表单的目录就在app/Resources/views,因为Bundle中找不到,所以结果在:form

---引用基础的表单块(Twig)---

到目前为止,重写一个特定的表单块,最好的方式是从form_div_layout.html.twig中复制默认的块,粘贴到不同的模板中,并自定义它。更多情况下,当你自定义这些时,你通过使用基础的模板,使用引用表单块的方式来避免重复的粘贴。

这个很容易做到,但你的表单块在同一模板或独立模板中,他们可能会略有不同。

---从相同的模板中引用块作为表单---1

在你要渲染的表单模板中输入use标签来引入块:

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

现在,当这个块从 form_div_layout.html.twig 引入后,这个integer_widget块会调用base_integer_widget。这意味着,当你重定义integer_widget 块时,你能够引入你刚刚标记的,默认模板中的,原始块 base_integer_widget

1
2
3
4
5
{% block integer_widget %}
    <div class="integer_widget">
        {{ block('base_integer_widget') }}
    </div>
{% endblock %}

---从外部模板引用基础块---2

如果你的自定义表单位于外部模板,你可以通过使用 Twig 的 parent() 功能来引用基本块:

1
2
3
4
5
6
7
8
{# app/Resources/views/Form/fields.html.twig #}
{% extends 'form_div_layout.html.twig' %}
 
{% block integer_widget %}
    <div class="integer_widget">
        {{ parent() }}
    </div>
{% endblock %}

Note

当使用 PHP 作为模板引擎的时候将不可能引用基本块。你必须手动复制基本块的内容到你的新模板文件中。

---在整个应用程序范围内自定义---

如果你想要你的定制表单全局到你的应用程序,你能够通过在外部模板定制表单来实现它,然后将他导入到你的应用程序配置中:

---Twig---1

通过使用以下配置,当一个模板被渲染时,任何在form/fields.html.twig模板中的定义表单块都可以被全局使用。

1
2
3
4
5
# app/config/config.yml
twig:
    form_themes:
        - 'form/fields.html.twig'
    # ...
1
2
3
4
5
<!-- app/config/config.xml -->
<twig:config>
    <twig:form-theme>form/fields.html.twig</twig:form-theme>
    <!-- ... -->
</twig:config>
1
2
3
4
5
6
7
8
// app/config/config.php
$container->loadFromExtension('twig', array(
    'form_themes' => array(
        'form/fields.html.twig',
    ),
 
    // ...
));

默认情况下,当渲染表单时 Twig 使用 div 布局。然而,有些人可能更喜欢使用 table 渲染表单。使用 form_table_layout.html.twig 资源来调用这样的布局:

1
2
3
4
5
# app/config/config.yml
twig:
    form_themes:
        - 'form_table_layout.html.twig'
    # ...
1
2
3
4
5
<!-- app/config/config.xml -->
<twig:config>
    <twig:form-theme>form_table_layout.html.twig</twig:form-theme>
    <!-- ... -->
</twig:config>
1
2
3
4
5
6
7
8
// app/config/config.php
$container->loadFromExtension('twig', array(
    'form_themes' => array(
        'form_table_layout.html.twig',
    ),
 
    // ...
));

如果你只是想要在一个模板中修改,在你的模板文件中添加这样一行代码就可以了,而不用添加模板作为一个资源:

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

注意上面的form变量是模板视图变量,他被传入到你的模板中。

---PHP---2

通过使用以下配置,当一个模板被渲染时,任何在app/Resources/views/Form文件夹中自定义表单块都可以被全局使用。

1
2
3
4
5
6
7
# app/config/config.yml
framework:
    templating:
        form:
            resources:
                - 'AppBundle:Form'
    # ...
1
2
3
4
5
6
7
8
9
<!-- app/config/config.xml -->
<framework:config>
    <framework:templating>
        <framework:form>
            <resource>AppBundle:Form</resource>
        </framework:form>
    </framework:templating>
    <!-- ... -->
</framework:config>
1
2
3
4
5
6
7
8
9
10
11
12
13
// app/config/config.php
// PHP
$container->loadFromExtension('framework', array(
    'templating' => array(
        'form' => array(
            'resources' => array(
                'AppBundle:Form',
            ),
        ),
     ),
 
     // ...
));

默认情况下,当渲染表单时,php引擎使用div布局。有些人,可能喜欢用table渲染表单。那么你要调用FrameworkBundle:FormTable资源来做布局:

1
2
3
4
5
6
# app/config/config.yml
framework:
    templating:
        form:
            resources:
                - 'FrameworkBundle:FormTable'
1
2
3
4
5
6
7
8
9
<!-- app/config/config.xml -->
<framework:config>
    <framework:templating>
        <framework:form>
            <resource>FrameworkBundle:FormTable</resource>
        </framework:form>
    </framework:templating>
    <!-- ... -->
</framework:config>
1
2
3
4
5
6
7
8
9
10
11
12
// app/config/config.php
$container->loadFromExtension('framework', array(
    'templating' => array(
        'form' => array(
            'resources' => array(
                'FrameworkBundle:FormTable',
            ),
        ),
    ),
 
     // ...
));

如果你只是想要在一个模板中有更改,在你的模板中添加下列这一行代码而不是将模板添加成资源:

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

注意上面的$form变量是模板视图变量,他被传入到你的模板中。

---如何去自定义一个单独的字段---

迄今为止,你已经看到了你能够使用不同的方法去定义所有text字段类型的组件输出。你也可以定义一个单独的字段。例如,假设在你的product表单中有两个text字段 - namedescription - 但是你只想定义其中的一个字段。他的片段名称是由字段的id属性组成,这部分的字段就可以被定义。例如,只定义一个name字段:

1
2
3
4
5
6
7
8
9
{% form_theme form _self %}
 
{% block _product_name_widget %}
    <div class="text_widget">
        {{ block('form_widget_simple') }}
    </div>
{% endblock %}
 
{{ form_widget(form.name) }}
1
2
3
4
5
6
7
8
9
<!-- Main template -->
<?php echo $view['form']->setTheme($form, array(':form')); ?>
 
<?php echo $view['form']->widget($form['name']); ?>
 
<!-- app/Resources/views/Form/_product_name_widget.html.php -->
<div class="text_widget">
    <?php echo $view['form']->block('form_widget_simple') ?>
</div>

在这里,_product_name_widget 片段自定义模板,使用idproduct_name的字段名(名字是product[name])。

Tip

这个product是表单的名称,他可以手动设置也可以根据你表单的类型名称自动生成(例如,ProductType 相当于product)。如果你不确定你表单的名字,那就查看生成表单的源。

如果你想要去改变这个product或者_product_name_widget块的名字,你应该在你的表单类型中设置block_name 配置选项:

1
2
3
4
5
6
7
8
9
10
11
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\TextType;
 
public function buildForm(FormBuilderInterface $builder, array $options)
{
    // ...
 
    $builder->add('name', TextType::class, array(
        'block_name' => 'custom_name',
    ));
}

然后这个块的名称将是_product_custom_name_widget

你也可以使用相同的方法来重写整个字段行:

1
2
3
4
5
6
7
8
9
10
11
{% 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) }}
1
2
3
4
5
6
7
8
9
10
11
<!-- Main template -->
<?php echo $view['form']->setTheme($form, array(':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>

---如何定义一个集合prototype---

当使用一个表单集合,prototype会被重写块的一个自定义的prototype完全覆盖。例如,如果你的表单字段名为tasks,你能够改变下每一个task的控件:

不仅可以重写渲染的控件,你也可以改变完整的表单行或者字段标签。上面给出了tasks字段,下面给出这个块的名称:

该表单的一部分块名称
label_tasks_entry_label
widget_tasks_entry_widget
row_tasks_entry_row

---其他常见的定义---

目前为止,本指导已经介绍过一些如何渲染表单的不同的自定义方法。关键就是要自定义特定的片段,这个片段和你想要控制的表单的属性相关。(请查看表单块的命名)。

接下来的章节中,你会看到几种常见的表单是如何定义的。为了这些表单的自定义,需要使用到表单主题化章节中的方法。

---自定义错误输出---1

Note

表单组件只处理错误的呈现,而不是实际处理验证的错误信息。这个错误信息本身取决于你对象的验证约束。更多信息,请查看 验证

当一个表单提交后出现错误信息,这个里有很多不同的方法可以渲染表单的错误信息。当你使用form_errors助手时,字段的错误信息就会被渲染:

1
{{ form_errors(form.age) }}
1
<?php echo $view['form']->errors($form['age']); ?>

默认情况下,这个错误被渲染在一个无序列表中:

1
2
3
<ul>
    <li>This field is required</li>
</ul>

如何重写所有渲染字段的错误信息,简单就是复制,粘贴并定义form_errors 片段:

1
2
3
4
5
6
7
8
9
10
11
12
{# 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 %}
1
2
3
4
5
6
7
8
<!-- form_errors.html.php -->
<?php if ($errors): ?>
    <ul>
        <?php foreach ($errors as $error): ?>
            <li><?php echo $error->getMessage() ?></li>
        <?php endforeach ?>
    </ul>
<?php endif ?>

Tip

如何应用这些自定义参见表单主题化

你也可以自定义这些错误输出仅为一个特定的字段类型。去定义仅有的标记用于这些错误,遵循和上面相同的方式但是把内容放到相关的 _errors 块(或者php模板文件中)。例如,text_errors(或者text_errors.html.php)。

Tip

查看 表单片段命名 去找到你需要定义的特定块和文件。

在你的表单可以渲染全局错误(不分别在字段渲染错误)而是在你表单的顶部,一起把错误输出:

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

为了仅仅自定义这些错误所使用的标记,遵循和上面相同的指示,但是现在要检查compound变量是否设置为true。如果为true,这意味着目前渲染的是一个字段的集合(如一个整体的表单),而不仅仅是一个单独的字段:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{# 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 %}
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 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 ?>

---自定义“表单行”---2

当你能够管理它的时候,最简单的方式去渲染一个表单字段就是使用form_row功能,它能渲染字段的label,错误,和HTML控件。为了自定义渲染所有表单字段行所使用的标志,要重写form_row片段。例如,你想要在每一行的周围添加一个div的class属性:

1
2
3
4
5
6
7
8
{# form_row.html.twig #}
{% block form_row %}
    <div class="form_row">
        {{ form_label(form) }}
        {{ form_errors(form) }}
        {{ form_widget(form) }}
    </div>
{% endblock form_row %}
1
2
3
4
5
6
<!-- 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>

Tip

如何应用这些定义请查看 表单主题化

---添加一个“必填”的星号到字段Label---3

如果你想要将你的所有的必填字段加上必填星号标注(*),你可以通过个性化 form_label 片段来完成。

在 Twig 中,如果你正在你的表单的相同的模板中自定义表单,修改 use 标签并且添加下列代码:

1
2
3
4
5
6
7
8
9
{% 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 中,如果你正在表单的不同的模板中自定义表单,使用下列代码:

1
2
3
4
5
6
7
8
9
{% extends 'form_div_layout.html.twig' %}
 
{% block form_label %}
    {{ parent() }}
 
    {% if required %}
        <span class="required" title="This field is required">*</span>
    {% endif %}
{% endblock %}

当使用 PHP 作为模板引擎时你必须从原始模板中复制内容:

1
2
3
4
5
6
7
8
9
10
11
12
<!-- 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 ?>

Tip

如何应用这些定义请查看 表单主题化

仅使用 CSS

默认情况下,一个required CSS 类可以去渲染label标签的必填字段。因此,你也可以只使用 CSS 来添加星号标注:

1
2
3
label.required:before {
    content: "* ";
}

---添加“帮助”信息---4

你也可以让你的自定义、表单控件拥有一个“帮助”信息的配置选项。

在 Twig 中,如果你正在表单的相同的模板中自定义表单,修改 use 标签并且添加下列代码:

1
2
3
4
5
6
7
8
9
{% 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 中,如果你正在表单的不同的模板中自定义表单,使用下列代码:

1
2
3
4
5
6
7
8
9
{% extends 'form_div_layout.html.twig' %}
 
{% block form_widget_simple %}
    {{ parent() }}
 
    {% if help is defined %}
        <span class="help">{{ help }}</span>
    {% endif %}
{% endblock %}

当使用 PHP 作为模板引擎时你必须从原始模板中复制内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 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变量:

1
{{ form_widget(form.title, {'help': 'foobar'}) }}
1
<?php echo $view['form']->widget($form['title'], array('help' => 'foobar')) ?>

Tip

如何应用这些定义请查看 表单主题化

---使用表单变量---

大部分的函数可用于渲染表单的不同部分(例如表单控件,表单标签,表单错误等等)都可以允许你直接做特定的自定义。看下面这个例子:

1
2
{# render a widget, but add a "foo" class to it #}
{{ form_widget(form.name, { 'attr': {'class': 'foo'} }) }}
1
2
3
4
5
6
<!-- render a widget, but add a "foo" class to it -->
<?php echo $view['form']->widget($form['name'], array(
    'attr' => array(
        'class' => 'foo',
    ),
)) ?>

这个包含表单“变量”的数组作为第二个参数传递。更多细节请查看,Reference分类下的Form Variables .

本文,包括例程代码在内,采用的是 Creative Commons BY-SA 3.0 创作共用授权。

登录symfonychina 发表评论或留下问题(我们会尽量回复)