参考:https://blog.csdn.net/liebert/article/details/77414217
目录
一、模板引擎工作原理
如上图所示,模板引擎主要的工作就是将数据和模板片段文件综合在一起,并最终生成HTML页面文件。
1.加载参数。加载模板引擎的相关配置参数,比如模板输出的缓存路径、编码方式、是否优化、是否缓存等配置信息。
2.检查校验。检查模板缓存路径是否存在、缓存路径能否读写、是否渲染并缓存、缓存是否过期等等信息。
3.解析检查。解析器检查语法正误,解析预编译指令,加载相关文件片段,最终生成抽象语法树。
4.编译执行。根据解析后的抽象语法树执行,一般地,这部分工作主要是由PHP Zend引擎来完成的。
5.渲染输出。从缓存中获取Zend执行后的最终输出流,并对最终数据的HTTP响应头部进行设置。
二、Twig模板引擎
Twig是功能最全面的现代PHP模板引擎之一,也是最快速的引擎之一。Twig将模板编译为纯粹的优化PHP代码,因此系统开销很小。其特性是原生模板继承,在其中将模板编译为类;在编译过程中完成自动转义,并且有一种安全的沙盒模式。所有这些特性为Twig提供了良好的扩展性。灵活的词法分析程序和分析器让开发人员能够定义自己的标记、过滤器等。
1.运行环境要求
Twig至少需要PHP5.2.4来运行。通过git命令行工具下载:
git clone git://github.com/twigphp/Twig.git
2.基本API用法
require_once '/path/to/vendor/autoload.php';
$loader = new Twig_Loader_Array(array(
'index' => 'Hello {{ name }}!',
));
$twig = new Twig_Environment($loader);
echo $twig->render('index', array('name' => 'Fabien'));
Twig使用加载器(Twig_Loader_Array)去加载模板,使用环境配置器(Twig_Environment)加载具体的配置参数。模板渲染方法render()第一个参数是加载的模板内容,第二个参数是传递给模板中用到的变量。通常模板以文件形式存放在文件系统中,并配合文件系统加载器一起使用:
loader = new Twig_Loader_Filesystem('/path/to/templates');
$twig = new Twig_Environment($loader, array(
'cache' => '/path/to/compilation_cache',
));
3.设计模板
模板就是一个简单的文本文件,可以是基于文本格式(如HTML、XML、CSV等),没有明确的文件格式,像.html、.xml都是可以的。模板中包含在解析时用于替换的变量和表达式,以及控制模板逻辑的标签。下面通过一个典型的模板最小结构来阐述基础知识,后面我们再做详细地讨论:
<!DOCTYPE html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
<h1>My Webpage</h1>
{{ a_variable }}
</body>
</html>
这里有两个分隔符: {% ... %} 和{{ ... }},{% ... %}用于执行像for循环这样的语句,{{ ... }}用于输出模板表达式的结果。此外,{# ... #}表示注释语句。
(1)变量输出
变量由具体的应用通过手动的方式传递给模板,你也可以在模板中访问变量包含的元素和属性,具体操作如下所示,使用“.”来访问变量的属性或元素:
{{ foo.bar }}
{{ foo['bar'] }}
如果属性的名称中包含特殊字符(像字符‘-’在解析的时候可能被理解为减法操作符),你可以使用atribute()函数来访问变量的属性。
{# 相当于不能正常工作的 foo.data-foo #}
{{ attribute(foo, 'data-foo') }}
a.全局变量
_self: 当前模板的名字
_context: 当前的上下文
_charset: 当前的字符编码
b.设置变量
通过‘set’标签,你可以在代码块中进行变量设置操作:
{% set foo = 'foo' %}
{% set foo = [1, 2] %}
{% set foo = {'foo': 'bar'} %}
(2)过滤器标签
使用过滤器可以对变量进行修改,在代码中,变量和过滤器、以及多个过滤器之间使用管道符‘ | ’来进行分隔。多个过滤器将依次对其进行操作,前一个过滤输出作为下一个过滤输入。如下所示,变量name经过滤器 striptags() 和 title() 的操作后,字符串中多余的空白字符会被移除,并且每个单词的首字母变成大写:
{{ name|striptags|title }} #多个过滤器的情况
【striptags标签 用法】-------------- twig的标签、函数和过滤器用法可参考:https://twig.symfony.com/doc/2.x/
过滤器 striptags
将清除SGML/XML标签,并且用一个空白替换邻近的空格:
| |
你也可以设置保留的标签,如下所示:
| |
这个例子中,标签<br/>
, <br>
, <p>
, 和</p>
将保留在子字符串中,并不会被清除。
过滤器也可以接受参数输入,下面这个例子中,list中的元素将以‘,’拼接 join() 在一起。
{{ list|join(',') }}
下面代码中使用过滤器filter,对包含在 filter标签 之内的字符串做upper(),即转化为大写:
{% filter upper %} #过滤器模板函数
This text becomes uppercase
{% endfilter %}
(3)函数标签
调用函数主要是用于生成内容,如下所示调用 range() 函数 返回一个等差数组:
{% for i in range(0, 3) %}
{{ i }},
{% endfor %}
(4)命名参数
通过命名参数,可以让代码变得更加语义化和便于理解。
{{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}
{# versus #}
{{ data|convert_encoding(from='iso-2022-jp', to='UTF-8') }} #from和to都是命名参数
命名参数,也可以让你跳过函数的某些参数,这样就不会影响到参数的默认值。
{# 第一个参数用于格式化时间,如果不设置的话就是用全局的默认时间格式化参数 #}
{{ "now"|date(null, "Europe/Paris") }}
{# 通过使用命名参数就可以跳过时间格式化参数直接设置时区#}
{{ "now"|date(timezone="Europe/Paris") }}
(5)控制结构
控制结构主要是指程序的流程控制,比如条件语句、循环语句。如下所示,在{% ... %}代码块中就是 for循环 的控制结构,通过循环变量users集合,输出每个元素的username:
<h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
加入 if标签 来进行条件的判断:
{% if users|length > 0 %}
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}
(6)注释
使用标识符{# ... #}来对模板中的一些内容进行注释,以便于开发者进行调试和理解。
{# note: disabled template because we no longer use this
{% for user in users %}
...
{% endfor %}
#}
(7)引入其他模板
模板的 include()函数 用于引入其他的子模板,并在当前位置直接输出模板渲染后的内容:
{{ include('sidebar.html') }}
默认地,被引入的模板(子模板)的上下文与引入它的模板(主模板)是一样的。也就说,在主模板中定义的变量,同样可以在子模板中使用。如下代码所示:
{% for box in boxes %}
{{ include('render_box.html') }}
{% endfor %}
被引入的子模板render_box.html可以访问在主模板中定义的box变量。被引入模板的文件全名(含完整路径)是基于模板加载器的。比如,如果Twig_Loader_Filesystem允许你访问主目录下的模板文件,你就可以通过子目录去访问模板:
{{ include('sections/articles/sidebar.html') }}
(8)模板继承
Twig模板引擎最强大的地方就在于模板的继承。通过模板继承功能,你可以先创建一个公共的模板骨架,并在公共模板中定义一些子模板用来覆盖公共模板内容的 block标签 。下面我们首先定义一个基模板(公共模板):
<!DOCTYPE html>
<html>
<head>
{% block head %} #block标签,定义模板区块
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2011 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
</html>
在这个基模板中使用 block标签 定义了四个由子模板来填充的区块,block标签告诉模板引擎这个四个区块可能会由子模板来覆盖,也可以不进行覆盖(在子模板中不进行定义就可以,或者定义了区块但是注明了继承父模板中定义的内容)。子模板中就可以这样编写:
{% extends "base.html" %} #extends标签,定义继承主模板
{% block title %}Index{% endblock %}
{% block head %}
{{ parent() }} # parent()函数,调用父模板该区块的内容
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome to my awesome homepage.
</p>
{% endblock %}
extends标签 是关键所在,它为模板引擎指明了当前模板是继承自哪个父模板。模板引擎会首先加载父模板,所以extends标签应当放在模板文件的最开始位置。需要注意的是:如果子模板未定义footerblock,将会使用父模板中的内容替代。当然,使用 parent()函数 可以保留父模板中为此block定义的内容。
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ parent() }}
{% endblock %}
(9)HTML转义
在生成HTML文本时,这里存在一些的风险(一是HTML结构的完整性,二是XSS安全问题),就是包含字符串的变量可能会破坏到最终的HTML文本,这里主要有两种手段:一种是手动地为每个变量进行转义,另一个是自动地为每个默认的变量进行转义。Twig支持上述两种方式,默认为自动进行转义。
a.手动转义
如果启用了手动转义,那么你就要负责那些需要进行转义的变量,哪些变量需要进行转义呢?任何你不信任的变量。
转义工作主要使用 过滤器escape 或者用 e管道 (默认使用html策略)来完成:
{{ user.username|e }}
默认的话,e使用html策略,对于js、css等其他特殊文本,可用以下方式指定策略:
{{ user.username|e('js') }}
{{ user.username|e('css') }}
{{ user.username|e('url') }}
{{ user.username|e('html_attr') }}
b.自动转义
对需要进行转义的部分,可采用 autoescape标签 (默认采用html策略)标记出来。
{% autoescape %}
Everything will be automatically escaped in this block (using the HTML strategy)
{% endautoescape %}
默认的话,自动转义采用的html策略,对于js、css等其他特殊文本,可用以下方式指定策略:
{% autoescape 'js' %}
Everything will be automatically escaped in this block (using the JS strategy)
{% endautoescape %}
(10)字符转义
有时候,为防止一些字符与Twig中使用的字符产生冲突,需要进行转义。比如在下面的例子中,如果想以原始方式输出字符串“{{”(并不是Twig的变量标签定义),就需要进行转义。比较简单的方式如下所示:
{{ '{{' }}
(11)宏定义
在正则编程语言中宏的概念等同于函数,它通常的作用就是 复用HTML片段,消除重复性工作。在Twig中使用 macro标签 进行定义,下面这个例子中,我们在 模板文件forms.html 中定义了一个用于渲染form元素的宏:
{% macro input(name, value, type, size) %} # 定义宏命令
<input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
{% endmacro %}
在所有引入了forms.html模板文件中都使用这个宏输出这个元素:
{% import "forms.html" as forms %} # 导入宏命令
<p>{{ forms.input('username') }}</p> #使用input宏命令
你也可以使用form标签将模板中个别宏引入到当前的名称空间中,并赋予一个别名:
{% from 'forms.html' import input as input_field %}
<dl>
<dt>Username</dt>
<dd>{{ input_field('username') }}</dd>
<dt>Password</dt>
<dd>{{ input_field('password', '', 'password') }}</dd>
</dl>
你可以在宏参数设置默认值,这样的话,在调用宏的时候就可以不提供这些参数值:
{% macro input(name, value = "", type = "text", size = 20) %}
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" />
{% endmacro %}
如果在调用宏的时候传入了额外的参数,那么这些参数都会被保存到名为 varargs变量 中,作为列表中的一项。
(12)表达式
Twig与PHP代码一样,允许在任何地方使用表达式。
a.字面量
最简单的表达式就是字面量,典型的代表就是:字符串、数字和数组。
"Hello World":字符串
42 或42.23:整数或浮点数
["foo","bar"]:数组
{"foo":"bar"}:哈希数组
true 或false:
null:
数组和哈希数据可以进行嵌套操作:
{% set foo = [1, {"foo": "bar"}] %}
b.算术运算符
+:对两个对象做加法操作,这个操作主要是针对数字,{{1 + 1 }} 等于 2
-:对两个对象做加法操作,{{ 3 - 2 }}等于 1
/:除法操作,返回值是一个浮点数, {{ 1 /2 }} 等于 {{ 0.5 }}
%:模运, {{ 11 % 7 }} 等于4.
//:两次除法运算,{{ 20 // 7 }} 等于 2, {{ -20 // 7 }} 等于 -3
*:乘法运算,{{ 2 * 2 }} 返回4
**:幂运算,{{ 2 ** 3 }} 返回8
c.逻辑运算符
and:与,左边和右边表达式均为true返回true,否则为false
or: 或,左边和右边表达式均为false返回false,否则为true
not: :取反
(expr) :表达式组
d.比较操作符
以下比较操作符在所有的表达式中都是被支持的:==、!=、<、>、>=、<=。你可以检查字符串是否以另一个字符串开始(starts with)或者结束(endswith):
{% if 'Fabien' starts with 'F' %}
{% endif %}
{% if 'Fabien' ends with 'n' %}
{% endif %}
e.包含操作符
判断左边部分是否被包含在右边,返回true或者false:
{# returns true #}
{{ 1 in [1, 2, 3] }}
{{ 'cd' in 'abcde' }}
与上述判断相反,使用not in:
{% if 1 not in [1, 2, 3] %}
{# is equivalent to #}
{% if not (1 in [1, 2, 3]) %}
f.其他操作符
|:应用过滤器
“..”:创建一个序列。
{{ 1..5 }}
{# equivalent to #}
{{ range(1, 5) }}
“~”:转换所有的操作。
“.” 和 “[ ]”:获取对象的属性。
“? ::”:三元运算符。
{{ foo ? 'yes' : 'no' }}
{{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }}
{{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }}
“??”:空结合运算符
{# 如果已经定义或者不为null返回foo, 否则返回'no' #}
{{ foo ?? 'no' }}
g.字符串插补
在由双引号括起来的字符串中,插补有效的表达式可写为“ #{ 表达式 } ”,最终字符串中插入的是表达式计算后的值:
{{ "foo #{bar} baz" }}
{{ "foo #{1 + 2} baz" }}
(13)空白字符控制
使用 spaceless标签,可以移除HTML标签之间的全部空白字符:
{% spaceless %}
<div>
<strong>foo bar</strong>
</div>
{% endspaceless %}
{# output will be <div><strong>foo bar</strong></div> #}
移除字符串头部和尾部的全部空白字符,可以简写为 {{- 变量 -}}:
{% set value = ' no spaces ' %}
{# No leading/trailing whitespace #}
{% if true %}
{{- value -}}
{% endif %}
{# output 'no spaces' #}
移除指定边的空白字符 {{- 变量 }},如下所示,移除变量value左边的全部空白字符:
{% set value = 'no spaces' %}
<li> {{- value }} </li>
{# outputs '<li>no spaces </li>' #}
(14)如何写一个自定义的Twig扩展
写扩展的主要目的就是把经常用到的代码移植到一个可重用的类中,比如说添加国际化支持。扩展可以定义(标签)tag,(筛选)filters,(测试)tests,(运算符)operators,(全局变量)global variables,(函数)functions 和(访问节点)node visitors。
创建一个扩展也有助于更好的代码分离,此处的代码包括编译时和运行时所需的代码。因此,它使你的代码更快。在编写自己的扩展之前,看一看Twig管方扩展库。
a)创建扩展类
如果你想使用Twig自定义功能,首先创建一个自定义Twig扩展类。作为一个例子,你需要创建一个价格过滤器来格式化给定的价格(也就是说把数字转化为价格的格式):
// src/AppBundle/Twig/AppExtension.php
namespace AppBundle\Twig;
class AppExtension extends \Twig_Extension # 定义twig扩展类
{
public function getFilters() # 返回过滤器类
{
return array(
new \Twig_SimpleFilter('price', array($this, 'priceFilter')),
);
}
public function priceFilter($number, $decimals = 0, $decPoint = '.', $thousandsSep = ',') # 定义过滤器逻辑
{
$price = number_format($number, $decimals, $decPoint, $thousandsSep);
# number_format ( float $number [, int $decimals = 0 ] ) : string — 以千位分隔符方式格式化一个数字
# number_format ( float $number , int $decimals = 0 , string $dec_point = "." , string $thousands_sep = "," ) : string
# 本函数可以接受1个、2个或者4个参数(注意:不能是3个):
# 如果只提供第一个参数,number的小数部分会被去掉 并且每个千位分隔符都是英文小写逗号","
# 如果提供两个参数,number将保留小数点后的位数到你设定的值
# 如果提供了四个参数,number 将保留decimals个长度的小数部分, 小数点被替换为dec_point,千位分隔符替换为thousands_sep
# decimals小数部分长度 $dec_point小数点符号 $thousands_sep千分位符号
$price = '$'.$price;
return $price;
}
public function getName()
{
return 'app_extension';
}
}
除了自定义过滤器,您还可以添加自定义函数和注册全局变量。
b)注册一个扩展为服务
现在,你必须让服务容器知道你新创建了一个Twig扩展---AppExtension:
YAML文件
# app/config/services.yml
services:
app.twig_extension:
class: AppBundle\Twig\AppExtension
public: false
tags:
- { name: twig.extension }
XML文件
<!-- app/config/services.xml -->
<services>
<service id="app.twig_extension"
class="AppBundle\Twig\AppExtension"
public="false">
<tag name="twig.extension" />
</service>
</services>
PHP文件
// app/config/services.php
use Symfony\Component\DependencyInjection\Definition;
$container
->register('app.twig_extension', '\AppBundle\Twig\AppExtension')
->setPublic(false)
->addTag('twig.extension');
c)使用自定义的扩展
使用您新创建的 Twig 扩展和使用其它扩展没有什么不同:
{# outputs $5,500.00 #}
{{ '5500'|price }}
传入其他参数到你的过滤器:
{# outputs $5500,2516 #}
{{ '5500.25155'|price(4, ',', '') }} # 小数点被替换为',',千分位被替换为空''字符
(15)Symfony Twig扩展
a)Twig函数¶
render:
{{ render(uri, options = []) }}
{#
uri
值类型: string | ControllerReference
可以由其他函数来生成,像是 path and url.
options (可选)
值类型: array 默认值: []
#}
为给定的控制器或URI渲染(页面的)片断 (使用 controller('bundle:controller:action') 函数)。更多信息,请参考 如何在模板中嵌入控制器 。
{# if the controller is associated with a route, use the path() or
url() functions to generate the URI used by render() #}
{{ render(path('latest_articles', {num: 5})) }}
{{ render(url('latest_articles', {num: 5})) }}
{# if you don't want to expose the controller with a public URL, use
the controller() function to define the controller to be executed #}
{{ render(controller('App\\Controller\\DefaultController::latestArticles', {num: 5})) }}
# 这种格式'App\\Controller\\DefaultController::latestArticles',也对
渲染策略可以在 strategy
键选项中指定。
render_esi:
{{ render_esi(uri, options = []) }}
{#
uri
值类型: string | ControllerReference
可以由其他函数来生成,像是 path and url.
options (可选)
值类型: array 默认值: []
#}
在可能的情况下生成一个ESI标签,或者回滚到 render 函数的行为。 更多信息,参考 如何在模板中嵌入控制器。render_esi( ) 是 render
快捷方法的一个例子。它自动地基于函数名称所给定的(策略信息)来设置策略,比如 render_hinclude( )
将使用 hinclude.js 策略。这种方式适用于所有 render_*()
函数。
controller:
{{ controller(controller, attributes = [], query = []) }}
{#
controller
值类型: string
attributes (可选)
值类型: array 默认值: []
query (可选)
值类型: array 默认值: []
#}
返回 ControllerReference
实例,用于诸如 render() 和 render_esi() 等函数。
path:
{{ path(name, parameters = [], relative = false) }}
{#
name
值类型: string
parameters (可选)
值类型: array 默认值: []
relative (可选)
值类型: boolean 默认值: false
#}
为给定的路由返回相对URL (没有scheme和host)。如果 relative
开启,它将创建一个相对于当前路径的path。更多信息请参考 链接到页面。阅读 路由 to 以了解更多关于路由组件的内容。
relative_path:
{{ relative_path(path) }}
{#
path
值类型: string
#]
从传入的绝对路径中,返回相对URL。例如,假设你访问的是这个程序页面:http://example.com/products/hover-board
。
{{ relative_path('http://example.com/human.txt') }}
{# ../human.txt #}
{{ relative_path('http://example.com/products/products_icon.png') }}
{# products_icon.png #}
url:
{{ url(name, parameters = [], schemeRelative = false) }}
{#
name
值类型: string
parameters (可选)
值类型: array 默认值: []
schemeRelative (可选)
值类型: boolean 默认值: false
#}
为给定的路由返回绝对对URL (有scheme和host) 。如果 schemeRelative
开启,它将创建一个scheme-relative的URL(相对于scheme)。更多信息请参考 链接到页面。
absolute_url:
{{ absolute_url(path) }}
{#
path
值类型: string
#}
从传入的相对路径中,返回绝对URL。例如,假设你访问的是这个程序页面:http://example.com/products/hover_board
。
{{ absolute_url('/human.txt') }}
{# http://example.com/human.txt #}
{{ absolute_url('products_icon.png') }}
{# http://example.com/products/products_icon.png #}
asset:
{{ asset(path, packageName = null) }}
{#
path
值类型: string
packageName (可选)
值类型: string | null 默认值: null
#}
返回 path
的public路径,该路径负责打点 “设置给package的基本路径” 和 “URL路径” 。更多信息请参考 连接到assets。对于asset versioning(资源版本),参考 version。
assets_version:
{{ assets_version(packageName = null) }}
{#
packageName (可选)
值类型: string | null 默认值: null
#}
返回package的当前版本,更多信息请参考 链接到Assets.
form:
{{ form(view, variables = []) }}
{#
view
值类型: FormView
variables (可选)
值类型: array 默认值: []
#}
{# 例子 #}
{# render the form and change the submission method #}
{# 渲染表单,同时更改提交method #}
{{ form(form, {'method': 'GET'}) }}
返回一个完整表单的HTML标签,更多信息请参考 Twig表单参考。form_start:
{{ form_start(view, variables = []) }}
{# render the start tag and change the submission method #}
{# 渲染表单的开始标签,同时更改提交method #}
{{ form_start(form, {'method': 'GET'}) }}
返回一个表单的HTML开始标签,更多信息请参考 Twig表单参考。
form_end:
{{ form_end(view, variables = []) }}
{{ form_end(form) }} #例子
返回一个表单的HTML结束标签,更多信息请参考 Twig表单参考。
form_widget:
{{ form_widget(view, variables = []) }}
{# render a widget, but add a "foo" class to it #}
{# 渲染表单字段的小部件,但为它添加一个“foo”的CSS class #}
{{ form_widget(form.name, {'attr': {'class': 'foo'}}) }}
form_widget
的第二个参数是一个由变量组成的数组。最常用的变量是 attr
,它是一个HTML属性的数组,用在HTML widget上。在一些场合中,特定的types也会有其他一些“与模板相关”的选项可以传进来。后面会逐类型地进行基本功能讨论。 attributes
在你一次输出很多字段时 (比如通过 form_widget(form)
),并不递归地作用于子字段。参见 "表单变量的更多内容" 以了解更多关于 variables
参数的内容。
Variable | Usage |
---|---|
form | 当前 FormView 实例。 |
id | 要渲染的 id HTML属性。 |
name | 字段名称 (如 title ) - 它不是 name HTML属性,HTML属性是 full_name 。 |
full_name | 要渲染的 name HTML属性。 |
errors | 附在特殊的 this 字段(如 form.title.errors ) 上的一个“任意错误信息”的数组。注意,你不可以使用 form.errors 来决定一个表单是否通过验证,因为它返回的是一个“全局”的错误:而某些个体字段是有自己的错误信息的。使用 valid 选项来替代。 |
submitted | 返回 true 或 false ,取决于是否提交了整个表单。 |
valid | 返回 true 或 false ,取决于是否整个表单通过了验证。 |
value | 渲染时要用到的值 (通常就是 value HTML属性)。 |
disabled | 如果是 true , disabled="disabled" 将被添加到字段中。 |
required | 如果是 true , 一个 required 属性将被添加到字段中,以激活(现代浏览器的)HTML5验证。 此外,一个 required class会被添加到label中。 |
label | 将被渲染的字符串label。 |
multipart | 如果是 true , form_enctype 将被渲染为 enctype="multipart/form-data" 。只适用于根表单元素(root form element)。 |
attr | 一个键值型数组,将作为字段的HTML属性而被渲染。 |
label_attr | 一个键值型数组,将作为label的HTML属性而被渲染。 |
compound | 某个字段是否为“一组子字段”的真正宿主(holder。例如,一个 choice 字段,确定会有一组checkboxes)。 |
block_prefixes | 所有父类型名称的一个数组。 |
translation_domain | 当前表单的翻译域(translation domain)。 |
cache_key | 一个用于缓存的唯一键。 |
data | 字段类型的normalized数据。(译注:要参考sf表单原理) |
method | 当前表单的method (POST, GET, 等等)。 |
action | 当前表单的action。 |
form_errors:
{{ form_errors(view) }}
{# 对name域的错误进行输出 #}
{{ form_errors(form.name) }}
{# render any "global" errors #}
{# 对任何“全局”错误信息进行输出 #}
{{ form_errors(form) }}
渲染(译注:由程序向模板输出的过程,在Symfony中常被称作渲染)给定字段的任何错误信息,或全局错误,更多信息请参考 Twig表单参考。
form_label:
{{ form_label(view, label = null, variables = []) }}
{# 默认label #}
{{ form_label(form.name) }}
{# The two following syntaxes are equivalent #}
{# 以下两种语法是等同的 #}
{{ form_label(form.name, 'Your Name', {'label_attr': {'class': 'foo'}}) }}
{{ form_label(form.name, null, {
'label': 'Your name',
'label_attr': {'class': 'foo'}
}) }}
渲染给定字段的label部分,请参考 Twig表单参考。了解关于 variables
参数,请参考 "表单变量的更多内容" 。
form_row:
输出给定字段的“row”,每个字段行包括:字段label,字段错误信息,字段小部件(译注:widget即构成表单的最核心部分,比如一个input标签)。
{{ form_row(view, variables = []) }}
{# render a field row, but display a label with text "foo" #}
{# 输出一个字段的完整行,但显示label文本为“foo” #}
{{ form_row(form.name, {'label': 'foo'}) }}
form_row
的第二个参数是由变量组成的一个数组。Symfony中提供的模板,只允许像上例那样覆写labels。参见 "表单变量的更多内容" 以了解更多关于 variables
参数的内容(见form_widget)。
form_rest:
{{ form_rest(view, variables = []) }}
{{ form_rest(form) }}
对某个给定表单,输出所有“尚未被渲染”的那些字段内容。在表单中的某处使用此函数是个好办法,因为它会帮你渲染隐藏字段,并且会把你已忘记的字段显示出来(因为它会帮你渲染该字段)。更多信息请参考 Twig表单参考。
csrf_token:
{{ csrf_token(intention) }}
{#
intention
值类型: string
#}
渲染一个CSRF token。当你“没有创建表单”时,若需要CSRF防护,可以使用本函数。
is_granted:
{{ is_granted(role, object = null, field = null) }}
role
值类型: string
object (可选)
值类型: object
field (可选)
值类型: string
如果当前用户拥有所需的role的话,结果将返回 true
。可选的object参数,可以传入一个Voter需要用到的对象。更多信息,可以在 模版中的访问控制。如果你想在模版中检查当前用户是否具有一个role,可以使用内置的 这个is_granted()
helper函数:
Twig模板文件
{% if is_granted('ROLE_ADMIN') %}
<a href="...">Delete</a>
{% endif %}
PHP文件
<?php if ($view['security']->isGranted('ROLE_ADMIN')): ?>
<a href="...">Delete</a>
<?php endif ?>
可选的field参数,你也可以传入一个特定字段,以使用ACE。关于此部分的更多内容,参考 访问控制入口项的范围。关于系统安全Security方面的总结,请关注稍后发布的博客 “Symfony学习笔记之安全-----Security总结” 。
logout_path:
{{ logout_path(key = null) }}
{#
key (可选)
值类型: string
#}
为给定的firewall(防火墙)生成一个相对的logout URL(退出链接)。如果没有提供key,则URL的生成是针对“用户登陆进来时所用到的”防火墙。
logout_url:
{{ logout_url(key = null) }}
等同于 logout_path 函数,但是它只生成绝对URL而非相对。
expression:
在Twig中创建 Expression
实例。简单示例如下:
Twig文件
{% if is_granted(expression(
'"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
)) %}
<a href="...">Delete</a>
{% endif %}
PHP文件
<?php if ($view['security']->isGranted(new Expression(
'"ROLE_ADMIN" in roles or (user and user.isSuperAdmin())'
))): ?>
<a href="...">Delete</a>
<?php endif; ?>
关于表达式和security性的更多细节,参考 Security: 复杂的Access Controls表达式.
b)Twig变量过滤器¶
humanize:
{{ text|humanize }}
{#
text
值类型: string
#}
让一个技术向的名称变成人类可读 (如,把下划线改成空格,或把camelCase驼峰文本,比如 helloWorld
转换成 hello world
,其后对字符串大写)。
trans:
{{ message|trans(arguments = [], domain = null, locale = null) }}
{#
message
值类型: string
arguments (可选)
值类型: array 默认值: []
domain (可选)
值类型: string 默认值: null
locale (可选)
值类型: string 默认值: null
#}
把文本翻译成当前语种信息。更多信息请参考 模板中的翻译。trans和transchoice过滤器,可用于翻译变量文本和复杂表达式:
{{ message|trans }}
{{ message|transchoice(5) }}
{{ message|trans({'%name%': 'Fabien'}, "app") }} {# %name%为message文本中的参数 #}
{{ message|transchoice(5, {'%name%': 'Fabien'}, 'app') }}
Symfony提供了特殊的Twig标签(trans
和 transchoice
),用于对“静态文本块”信息提供翻译帮助。详细请参考: Symfony学习笔记之翻译-----translation总结 。在翻译时无论使用标签还是调节器,效果是相同的,但有一个微小区别:自动输出转义功能仅对调节器有效。换言之,如果你需要翻译出来的信息“不被转义”,则必须在translation调节器后面再跟一个raw调节器:
{# 标签中被翻译的文本从不被转义#}
{% trans %}
<h3>foo</h3>
{% endtrans %}
{% set message = '<h3>foo</h3>' %}
{# 变量过滤器中翻译的字符串和变量,默认将被转义 #}
{{ message|trans|raw }} {# raw强制不转义 #}
{{ '<h3>bar</h3>'|trans|raw }}
transchoice:
{{ message|transchoice(count, arguments = [], domain = null, locale = null) }}
{#
message
值类型: string
count
值类型: integer
arguments (可选)
值类型: array 默认值: []
domain (可选)
值类型: string 默认值: null
locale (可选)
值类型: string 默认值: null
#}
在对文本进行翻译时添加多元化(pluralization)的支持。更多信息请参考 模板中的翻译。
yaml_encode:
{{ input|yaml_encode(inline = 0, dumpObjects = false) }}
{#
input
值类型: mixed
inline (可选)
值类型: integer 默认值: 0
dumpObjects (可选)
值类型: boolean 默认值: false
#}
把输入的内容转换成YAML语法,参考 写入YAML文件 以了解更多。
yaml_dump:
{{ value|yaml_dump(inline = 0, dumpObjects = false) }}
{#
value
值类型: mixed
inline (可选)
值类型: integer 默认值: 0
dumpObjects (可选)
值类型: boolean 默认值: false
#}
和 yaml_encode()做同样的事,但却在输出内容中包括了类型(type)
abbr_class:
{{ class|abbr_class }}
{#
class
值类型: string
#}
生成一个 <abbr>
元素,带有一个PHP类的短名 (若用户把鼠标放在该元素上,会显示一个FQCN的tooltip提示框)。
abbr_method:
{{ method|abbr_method }}
{#
method
值类型: string
#}
生成一个 <abbr>
元素,使用了 FQCN::method()
语法。如果 method
是 Closure
的话, Closure
将被使用。如果 method
并没有一个类名的话,它会显示为一个函数 (method()
)。
format_args:
{{ args|format_args }}
{#
args
值类型: array
#}
生成一个带有参数及其类型的字符串 (在 <em>
元素中)。
format_args_as_text:
{{ args|format_args_as_text }}
等同于 format_args 过滤器,但不使用HTML标签。
file_excerpt:
{{ file|file_excerpt(line = null) }}
{#
file
值类型: string
line (可选)
值类型: integer
#}
围绕给定的 line
生成一个line行的摘要。
format_file:
{{ file|format_file(line, text = null) }}
{#
file
值类型: string
line
值类型: integer
text (可选)
值类型: string 默认值: null
#}
在 <a>
元素中生成一个文件路径。如果路径位于kernel root directory(kernel根目录),kernel root directory路径会被 kernel.root_dir
替代 (在鼠标hover状态下显示完整路径的提示框)。
format_file_from_text:
{{ text|format_file_from_text }}
{#
text
值类型: string
#}
使用 format_file 来改进默认的PHP错误信息输出。
file_link:
{{ file|file_link(line = null) }}
对给定的文件生成一个链接(行号是可选的),使用的是一个预配置(preconfigured)scheme。
c)Twig标签¶
form_theme:
{% form_theme form resources %}
{#
form
值类型: FormView
resources
值类型: array | string
#}
设置 resource 来覆写“给定的表单view实例” 之表单主题(form theme)。你可以使用 _self
作为 resources,即可把它设置为当前的resource。 更多内容请参考 如何自定义表单渲染http://www.symfonychina.com/doc/current/form/form_customization.html,或者浏览后面发布的Symfony学习笔记之表单渲染-----form总结。
trans:
{% trans with vars from domain into locale %}{% endtrans %}
{#
vars (可选)
值类型: array 默认值: []
domain (可选)
值类型: string 默认值: string
locale (可选)
值类型: string 默认值: string
#}
对内容的翻译进行渲染。更多内容请参考 Twig模板。
transchoice:
{% transchoice count with vars from domain into locale %}{% endtranschoice %}
{#
count
值类型: integer
vars (可选)
值类型: array 默认值: []
domain (可选)
值类型: string 默认值: null
locale (可选)
值类型: string 默认值: null
#}
对内容的翻译进行“支持多元化”的渲染。更多内容请参考 Twig模板。
trans_default_domain:
{% trans_default_domain domain %}
{#
domain
值类型: string
#}
对当前模板中的默认domain(翻译域)进行设置。
stopwatch:
{% stopwatch 'name' %}...{% endstopwatch %}
对标签内的代码的运行进行 “计时” ,并把相关信息置入WebProfilerBundle的时间线中。
d)Twig测试¶
selectedchoice:
{% if choice is selectedchoice(selectedValue) %}
{#
choice
类型: ChoiceView
selectedValue
类型: string
#}
检查 selectedValue
值是否被提交过来的choice字段所“选中(checked)”。使用它进行测试是最为高效的方式。
e)全局模板变量 ¶
app :
app
可以随处使用,可以访问到大量常用的对象连同其值。它是 GlobalVariables
的实例。
app.user
app.request
app.session
app.environment
app.debug
参考:https://blog.csdn.net/liebert/article/details/77414217
参考:如何写一个自定义的Twig扩展 和 symfony创建和使用模板
参考:Twig中文文档--看云