如何使用表单主题
表单输出的每一个部分都是可以进行自定义的。你可以随意地改变每一个表单“行”(form “row”)的渲染,改变用于输出错误的HTML标记,甚至自定义 textarea
标签应该如何输出。没有任何限制,不同的个性化设置可以用在不同的场合。
Symfony使用模板来渲染每一个或者部分的表单,比如label
标签,input
标签,错误信息以及任何其他内容。
在Twig中,每一个表单“片段”(fragment)是通过Twig block(模板代码区块)来渲染的。要自定义表单输出的任何一个部分,你只需要覆写相对应的block。
在PHP模板中,每个表单“片段”是通过单独的模板文件来渲染的,要自定义表单输出的任何一个部分,你只需通过创建新模板来覆盖旧模板。
要理解了它们是如何工作的,自定义 form_row
片段并添加一个class属性到“包裹了每一个表单行”的 div
元素中。要实现这个,先创建一个新的模板文件,用于存放新的HTML标记:
1 2 3 4 5 6 7 8 9 10 |
{# app/Resources/views/form/fields.html.twig #}
{% block form_row %}
{% spaceless %}
<div class="form_row">
{{ form_label(form) }}
{{ form_errors(form) }}
{{ form_widget(form) }}
</div>
{% endspaceless %}
{% endblock form_row %} |
1 2 3 4 5 6 |
<!-- app/Resources/views/form/form_row.html.php -->
<div class="form_row">
<?php echo $view['form']->label($form, $label) ?>
<?php echo $view['form']->errors($form) ?>
<?php echo $view['form']->widget($form, $parameters) ?>
</div> |
form_row
表单片段,会在多数字段经由 form_row
函数被渲染出来时使用。要告诉表单组件去使用你的新 form_row
片段,把下面代码添加到输出表单的模板顶部:
1 2 3 4 5 6 7 |
{# app/Resources/views/default/new.html.twig #}
{% form_theme form 'form/fields.html.twig' %}
{# or if you wAnt to use multiple themes / 或者,如果你希望使用多个主题 #}
{% form_theme form 'form/fields.html.twig' 'form/fields2.html.twig' %}
{# ... render the form #} |
1 2 3 4 5 6 7 |
<!-- app/Resources/views/default/new.html.php -->
<?php $view['form']->setTheme($form, array('form')) ?>
<!-- or if you want to use multiple themes -->
<?php $view['form']->setTheme($form, array('form', 'form2')) ?>
<!-- ... render the form --> |
form_theme
标签(Twig中的)“导入”了定义在给定模板中的片段,并且在输出表单的时候使用它们。换句话说,当 form_row
模板函数在模板中被调用后,它将从你的自定义主题中(而不是Symfony自带的 form_row
区块)去使用form_row
块。
你的个性化主题不必覆写所有的表单区块。当渲染一个“你未在个性化主题中进行覆写”的区块儿时,表单主题引擎会回滚到全局主题(在bundle级别进行了定义)。
在拥有多个自定义主题的情况下,在回滚到全局主题之前,会按照罗列的顺序进行搜索(并使用)。
要自定义你的表单的任何一部分,只需覆写适当的片段。准确地知道哪些区块或文件将被覆写,是下一小节的课题。
更多信息请参考 如何自定义表单渲染。
表单片段的命名 ¶
在Symfony中,表单所输出的每一部分 - HTML表单元素,错误信息,表单标签,等等 - 都是被定义在基础主题里面,基础主题是一个Twig的block区块集合,在PHP模板中它是一组模板文件的集合。
在Twig中,每一个所需的区块儿都被定义在一个单独的模板文件中(form_div_layout.html.twig),它们被存放在 Twig Bridge 里面。在这个文件中,你可以看到渲染一个表单时所需要的每一个block和默认的每一个字段类型(field type)。
在PHP模板中,片段是单独的模板文件。 它们默认存放于FrameworkBundle的 Resources/views/Form
目录下 (参见 gitHub)。
每个片段的命名,都遵循同一基本原则,其名字被一个下划线(_
)分割为两部分,下面是一些例子:
form_row
- 被form_row()
用来渲染大部分字段;textarea_widget
- 被form_widget()
用来渲染一个textarea
字段类型;form_errors
- 被form_errors()
用来渲染某字段的错误信息。
每个片段都遵循同一基本的命名原则:type_part
。type
部分对应被渲染的字段 类型 (如 textarea
, checkbox
, date
等),而 part
部分对应着是 什么 会被渲染(如label
, widget
, errors
等)。默认情况下,一个表单有4种可能的 parts 可以用来输出:
label |
(如 form_label() ) |
渲染字段的标签 |
widget |
(如 form_widget() ) |
渲染字段的html呈现 |
errors |
(如 form_errors() ) |
渲染错误信息 |
row |
(如 form_row() ) |
渲染字段一整行(包括label、widget、errors) |
Note
另外确实还有其他2个 part 类型 - rows
和 rest
- 不过你极少会有覆写这两个区块的需求。
通过知晓字段类型 (如 textarea
) 和你想自定义哪一部分(如 widget
),即可构建出需要覆写的片段之名称(如 textarea_widget
)。
模板片段的继承 ¶
在某些情况下,你想要进行自定义的片段可能会不存在。比如,Symfony提供的默认主题中并没有 textarea_errors
片段。那么如何来渲染一个textarea字段的错误信息呢?
答案是:通过 form_errors
片段。Symfony在输出一个textarea类型的错误时,在回滚到 form_errors
片段之前,它先去查找一个textarea_errors
片段。每个字段类型都有一个 parent type(父类型。textarea
的父类型是 text
,其父级是 form
),如果某个基础片段不存在,Symfony就会转而使用其父类型的片段。
所以,如果仅需覆写 textarea
字段的errors,拷贝 form_errors
片段,重命名为 textarea_errors
并对其自定义。要覆写 全体 字段类型的默认errors输出,应直接拷贝并定制 form_errors
片段。
Tip
对于每一种字段类型,form type reference/表单类型参考 中有每个字段类型的“parent”父类型。
全局的表单样式 ¶
在前面的例程中,我们使用了 form_theme
helper(仅限Twig模板)来把自定义的表单片段,仅“导入”到当前表单。你也可以告诉Symfony横跨整个项目来导入自定义表单(类型)。
Twig ¶
为了能在 所有 的模板里,从之前创建的 fileds.html.twig
模板中自动包容自定义的区块儿,修改你的程序级配置文件:
1 2 3 4 5 |
# app/config/config.yml
twig:
form_themes:
- 'form/fields.html.twig'
# ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="Http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:twig="http://symfony.com/schema/dic/twig"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/twig http://symfony.com/schema/dic/twig/twig-1.0.xsd">
<twig:config>
<twig:theme>form/fields.html.twig</twig:theme>
<!-- ... -->
</twig:config>
</container> |
1 2 3 4 5 6 7 |
// app/config/config.php
$container->loadFromExtension('twig', array(
'form_themes' => array(
'form/fields.html.twig',
),
// ...
)); |
现在,fields.html.twig
模板中的任何一个block都可以被全局地用来定义表单输出了。
PHP ¶
为了能在 所有 的模板里,从之前创建的 app/Resources/views/form
目录中自动包容自定义的模板,修改你的程序级配置文件:
1 2 3 4 5 6 7 |
# app/config/config.yml
framework:
templating:
form:
resources:
- 'form'
# ... |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<!-- app/config/config.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:framework="http://symfony.com/schema/dic/symfony"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
<framework:config>
<framework:templating>
<framework:form>
<framework:resource>Form</framework:resource>
</framework:form>
</framework:templating>
<!-- ... -->
</framework:config>
</container> |
1 2 3 4 5 6 7 8 9 10 11 |
// app/config/config.php
$container->loadFromExtension('framework', array(
'templating' => array(
'form' => array(
'resources' => array(
'Form',
),
),
),
// ...
)); |
现在,任何一个位于 AppBundle/Resources/views/Form
目录中的模板片段,都可以全局地用于定义表单输出了。