模板设计器的Twig¶
本文描述了模板引擎的语法和语义,对于那些创建Twig模板的人来说非常有用。
简介¶
模板是一个常规的文本文件。它可以生成任何基于文本的格式(HTML、XML、CSV、LaTeX等)。它没有特定的扩展名, .html
或 .xml
很好。
模板包含 变量 或 表达 ,在评估模板时将其替换为值,并且 tags ,控制模板的逻辑。
下面是一个最小的模板,它说明了一些基础知识。我们稍后将介绍更多细节:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!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循环之类的语句,后者输出表达式的结果。
IDEs集成¶
许多IDE支持Twig的语法高亮显示和自动完成:
- 文本匹配 通过 Twig bundle
- Vim 通过 Jinja syntax plugin 或 vim-twig plugin
- 网际网路 通过 Twig syntax plugin (直到7.1,从7.2开始为本地)
- PhpStorm (自2.1起为本机)
- 日食 通过 Twig plugin
- 升华文本 通过 Twig bundle
- GtkSourceView 通过 Twig language definition (gedit和其他项目使用)
- Coda 和 SubEthaEdit 通过 Twig syntax mode
- 尾2 通过 other Twig syntax mode
- 科莫多 和 科莫多编辑 通过twighighlight/syntax check模式
- 记事本++ 通过 Notepad++ Twig Highlighter
- 电子制造商 通过 web-mode.el
- Atom 通过 PHP-twig for atom
- Visual Studio代码 通过 Twig pack
也, TwigFiddle 是一个在线服务,允许您从浏览器执行Twig模板;它支持所有版本的Twig。
变量¶
应用程序将变量传递给模板,以便在模板中进行操作。变量也可以有你可以访问的属性或元素。变量的可视化表示在很大程度上依赖于提供它的应用程序。
使用点 (.
)要访问变量的属性(PHP对象的方法或属性,或PHP数组的项):
1 | {{ foo.bar }}
|
注解
重要的是要知道大括号 not 变量的一部分,但print语句。当访问标记中的变量时,不要将括号放在标记周围。
如果变量或属性不存在,则会收到 null
当 strict_variables
选项设置为 false
或者,如果 strict_variables
设置后,Twig将抛出一个错误(请参见 environment options )
注解
如果要访问变量的动态属性,请使用 attribute 而是函数。
这个 attribute
当属性包含特殊字符(如 -
这将被解释为减号运算符):
1 2 | {# equivalent to the non-working foo.data-foo #}
{{ attribute(foo, 'data-foo') }}
|
过滤器¶
变量可以修改为 过滤器 . 过滤器与变量之间用管道符号隔开 (|
). 可以链接多个过滤器。一个过滤器的输出应用于下一个过滤器。
下面的示例从 name
标题是:
1 | {{ name|striptags|title }}
|
接受参数的筛选器在参数周围有括号。此示例通过逗号连接列表中的元素:
1 | {{ list|join(', ') }}
|
若要对代码部分应用筛选器,请使用 apply 标签:
1 2 3 | {% apply upper %}
This text becomes uppercase
{% endapply %}
|
去 filters 页面以了解有关内置过滤器的更多信息。
功能¶
可以调用函数来生成内容。函数的名称后跟括号来调用 (()
)可能会有争论。
例如, range
函数返回一个包含整数算术级数的列表:
1 2 3 | {% for i in range(0, 3) %}
{{ i }},
{% endfor %}
|
去 functions 页面以了解有关内置函数的更多信息。
命名参数¶
1 2 3 | {% for i in range(low=1, high=10, step=2) %}
{{ i }},
{% endfor %}
|
使用命名参数可以使模板更明确地显示作为参数传递的值的含义:
1 2 3 4 5 | {{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}
{# versus #}
{{ data|convert_encoding(from='iso-2022-jp', to='UTF-8') }}
|
命名参数还允许您跳过某些不想更改其默认值的参数:
1 2 3 4 5 | {# the first argument is the date format, which defaults to the global date format if null is passed #}
{{ "now"|date(null, "Europe/Paris") }}
{# or skip the format value by using a named argument for the time zone #}
{{ "now"|date(timezone="Europe/Paris") }}
|
也可以在一个调用中同时使用位置参数和命名参数,在这种情况下,位置参数必须始终位于命名参数之前:
1 | {{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }}
|
小技巧
每个函数和筛选器文档页都有一个部分,其中列出了所有参数的名称(如果支持)。
控制结构¶
控制结构是指所有控制程序流的东西-条件句(即。 if
/elseif
/否则
), for
-循环,以及块之类的东西。控制结构出现在里面 {{% ... %}}
阻碍。
例如,要显示在名为 users
使用 for 标签:
1 2 3 4 5 6 | <h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
|
这个 if 标记可用于测试表达式:
1 2 3 4 5 6 7 | {% if users|length > 0 %}
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}
|
去 tags 页面以了解有关内置标记的更多信息。
评论¶
要注释掉模板中某行的一部分,请使用注释语法 {{# ... #}}
. 这对于调试或为其他模板设计器或您自己添加信息非常有用:
1 2 3 4 5 | {# note: disabled template because we no longer use this
{% for user in users %}
...
{% endfor %}
#}
|
包括其他模板¶
这个 include 函数可用于包含模板并将该模板的呈现内容返回到当前模板中:
1 | {{ include('sidebar.html') }}
|
默认情况下,包含的模板可以访问与包含它们的模板相同的上下文。这意味着主模板中定义的任何变量也将在包含的模板中可用:
1 2 3 | {% for box in boxes %}
{{ include('render_box.html') }}
{% endfor %}
|
包含的模板 render_box.html
能够访问 box
变量。
模板的名称取决于模板加载器。例如 \Twig\Loader\FilesystemLoader
允许您通过指定文件名来访问其他模板。可以使用斜杠访问子目录中的模板:
1 | {{ include('sections/articles/sidebar.html') }}
|
此行为取决于应用程序嵌入Twig。
模板继承¶
Twig最强大的部分是模板继承。模板继承允许您构建一个基本的“骨架”模板,该模板包含站点的所有公共元素并定义 阻碍 子模板可以重写。
从一个例子开始更容易理解这个概念。
让我们定义一个基本模板, base.html
,它定义了可用于两列页面的HTML框架文档:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <!DOCTYPE html>
<html>
<head>
{% block head %}
<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
标记的作用是告诉模板引擎子模板可能会覆盖模板的这些部分。
子模板可能如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | {% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ 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标记应该是模板中的第一个标记。
注意,因为子模板没有定义 footer
块,使用父模板中的值。
可以使用 parent 功能。这将返回父块的结果:
1 2 3 4 5 | {% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ parent() }}
{% endblock %}
|
小技巧
的文档页 extends 标记描述了更高级的特性,如块嵌套、作用域、动态继承和条件继承。
注解
Twig还通过“水平重用”在 use 标签。
HTML逃逸¶
当从模板生成HTML时,总是存在这样一种风险:变量将包含影响结果HTML的字符。有两种方法:手动转义每个变量或在默认情况下自动转义所有变量。
Twig同时支持这两种功能,默认情况下启用了自动转义。
自动转义策略可以通过 autoescape 选项,默认为 html
.
使用手动逃逸¶
如果启用了手动转义,则为 your 如果需要,有责任逃避变量。逃什么?来自不可信源的任何变量。
通过使用 escape 或 e
过滤器:
1 | {{ user.username|e }}
|
默认情况下, escape
过滤器使用 html
策略,但根据转义上下文,您可能希望显式使用其他策略:
1 2 3 4 | {{ user.username|e('js') }}
{{ user.username|e('css') }}
{{ user.username|e('url') }}
{{ user.username|e('html_attr') }}
|
使用自动转义¶
无论是否启用自动转义,都可以使用 autoescape 标签:
1 2 3 | {% autoescape %}
Everything will be automatically escaped in this block (using the HTML strategy)
{% endautoescape %}
|
默认情况下,自动转义使用 html
逃避策略。如果在其他上下文中输出变量,则需要使用适当的转义策略显式转义它们:
1 2 3 | {% autoescape 'js' %}
Everything will be automatically escaped in this block (using the JS strategy)
{% endautoescape %}
|
逃逸¶
有时需要甚至有必要让Twig忽略它将作为变量或块处理的部分。例如,如果使用了默认语法,并且您希望使用 {{{{
作为模板中的原始字符串而不是一个变量,你必须使用一个技巧。
最简单的方法是输出变量分隔符 ({{{{
)通过使用变量表达式:
1 | {{ '{{' }}
|
对于较大的部分,标记一个块是有意义的 verbatim .
表达¶
Twig允许表达式无处不在。
注解
运算符优先级如下,优先级最低的运算符列在最前面: ?:
(ternary operator), b-and
, b-xor
, b-or
, or
, and
, ==
, !=
, <=>
, <
, >
, >=
, <=
, in
, matches
, starts with
, ends with
, ..
, +
, -
, ~
, *
, /
, `` /; ``%` , is
(测试), **
, ??
, |
(过滤器), []
和 .
:
1 2 3 4 5 6 7 | {% set greeting = 'Hello ' %}
{% set name = 'Fabien' %}
{{ greeting ~ name|lower }} {# Hello fabien #}
{# use parenthesis to change precedence #}
{{ (greeting ~ name)|lower }} {# hello fabien #}
|
直接常量¶
最简单的表达式形式是文字。文字是PHP类型(如字符串、数字和数组)的表示。存在以下文字:
"Hello World"
:两个双引号或单引号之间的所有内容都是字符串。当您需要模板中的字符串时(例如,作为函数调用、过滤器的参数,或者只是为了扩展或包含模板),它们都很有用。如果字符串前面有反斜杠,则可以包含分隔符 (\
)--就像在'It\'s good'
. 如果字符串包含反斜杠(例如。'c:\Program Files'
)通过加倍来逃避(例如。'c:\\Program Files'
)42
/42.23
:整数和浮点数是通过写下数字来创建的。如果有一个点,这个数字是一个浮点数,否则是一个整数。["foo", "bar"]
:数组由逗号分隔的表达式序列定义 (,
)用方括号包起来 ([]
){{"foo": "bar"}}
:散列由逗号分隔的键和值列表定义 (,
)用大括号包着 ({{}}
):1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
{# keys as string #} { 'foo': 'foo', 'bar': 'bar' } {# keys as names (equivalent to the previous hash) #} { foo: 'foo', bar: 'bar' } {# keys as integer #} { 2: 'foo', 4: 'bar' } {# keys can be omitted if it is the same as the variable name #} { foo } {# is equivalent to the following #} { 'foo': foo } {# keys as expressions (the expression must be enclosed into parentheses) #} {% set foo = 'foo' %} { (foo): 'foo', (1 + 1): 'bar', (foo ~ 'b'): 'baz' }
true
/false
:true
代表真值,false
表示假值。null
:null
表示没有特定值。这是变量不存在时返回的值。none
是一个别名null
.
数组和哈希可以嵌套:
1 | {% set foo = [1, {"foo": "bar"}] %}
|
小技巧
使用双引号或单引号字符串对性能没有影响,但是 string interpolation 仅在双引号字符串中支持。
数学¶
Twig允许您在模板中进行数学运算;支持以下运算符:
+
:将两个数字相加(操作数转换为数字)。{{{{ 1 + 1 }}}}
是2
.-
:从第一个数字中减去第二个数字。{{{{ 3 - 2 }}}}
是1
./
:除以两个数字。返回值将是一个浮点数。{{{{ 1 / 2 }}}}
是{{{{ 0.5 }}}}
.%
:计算整数除法的余数。{{{{ 11 % 7 }}}}
是4
.//
:将两个数字相除并返回整数结果。{{{{ 20 // 7 }}}}
是2
,{{{{ -20 // 7 }}}}
是-3
(这只是 round 过滤器)。*
:将左操作数与右操作数相乘。{{{{ 2 * 2 }}}}
会回来4
.**
:将左操作数提升到右操作数的幂。{{{{ 2 ** 3 }}}}
会回来8
.
逻辑¶
可以使用以下运算符组合多个表达式:
and
:如果左操作数和右操作数都为true,则返回true。or
:如果左操作数或右操作数为真,则返回true。not
:否定语句。(expr)
:对表达式分组。
注解
Twig还支持按位运算符 (b-and
, b-xor
和 b-or
)
注解
运算符区分大小写。
比较¶
任何表达式都支持以下比较运算符: ==
, !=
, <
, >
, >=
和 <=
.
您还可以检查字符串 starts with
或 ends with
另一个字符串:
1 2 3 4 5 | {% if 'Fabien' starts with 'F' %}
{% endif %}
{% if 'Fabien' ends with 'n' %}
{% endif %}
|
注解
对于复杂字符串比较 matches
操作员允许您使用 regular expressions :
1 2 | {% if phone matches '/^[\\d\\.]+$/' %}
{% endif %}
|
安全壳操作员¶
这个 in
操作员进行密封试验。它回来了 true
如果左操作数包含在右操作数中:
1 2 3 4 5 | {# returns true #}
{{ 1 in [1, 2, 3] }}
{{ 'cd' in 'abcde' }}
|
小技巧
可以使用此筛选器对实现 Traversable
接口。
要执行阴性测试,请使用 not in
操作员:
1 2 3 4 | {% if 1 not in [1, 2, 3] %}
{# is equivalent to #}
{% if not (1 in [1, 2, 3]) %}
|
测试操作员¶
这个 is
操作员执行测试。测试可用于根据公共表达式测试变量。右操作数是测试的名称:
1 2 3 | {# find out if a variable is odd #}
{{ name is odd }}
|
测试也可以接受参数:
1 | {% if post.status is constant('Post::PUBLISHED') %}
|
可以使用 is not
操作员:
1 2 3 4 | {% if post.status is not constant('Post::PUBLISHED') %}
{# is equivalent to #}
{% if not (post.status is constant('Post::PUBLISHED')) %}
|
去 tests 页面以了解有关内置测试的更多信息。
其他经营者¶
以下运算符不适用于任何其他类别:
|
:应用筛选器。..
:基于运算符前后的操作数创建序列(这是 range 功能:1 2 3 4
{{ 1..5 }} {# equivalent to #} {{ range(1, 5) }}
注意,由于 operator precedence rules :
1
(1..5)|join(', ')
~
:将所有操作数转换为字符串并连接它们。{{{{ "Hello " ~ name ~ "!" }}}}
将返回(假设name
是'John'
)Hello John!
..
,[]
:获取变量的属性。?:
:三元运算符:1 2 3
{{ foo ? 'yes' : 'no' }} {{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }} {{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }}
??
:空合并运算符:1 2
{# returns the value of foo if it is defined and not null, 'no' otherwise #} {{ foo ?? 'no' }}
串插值¶
串插值 (#{{expression}}
)允许任何有效表达式出现在 double-quoted string . 计算该表达式的结果将插入到字符串中:
1 2 | {{ "foo #{bar} baz" }}
{{ "foo #{1 + 2} baz" }}
|
空白控件¶
模板标记后的第一个换行被自动删除(就像在PHP中)。模板引擎不会进一步修改空白,因此每个空白(空格、制表符、换行符等)都会原封不动地返回。
您还可以在每个标记级别上控制空白。通过在标记上使用空白控件修饰符,可以修剪前导空格和/或尾随空格。
Twig支持两个修改器:
- 空白修剪 通过
-
修饰符:删除所有空白(包括换行符); - 线条空白修剪 通过
~
修饰符:删除所有空白(不包括换行符)。在右边使用这个修饰符将禁用从PHP继承的第一个换行符的默认删除。
修饰符可以在标记的任一侧使用,如 {{%-
或 -%}}
它们会消耗标签那一边的所有空白。可以在标记的一侧或两侧使用修饰符:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | {% set value = 'no spaces' %}
{#- No leading/trailing whitespace -#}
{%- if true -%}
{{- value -}}
{%- endif -%}
{# output 'no spaces' #}
<li>
{{ value }} </li>
{# outputs '<li>\n no spaces </li>' #}
<li>
{{- value }} </li>
{# outputs '<li>no spaces </li>' #}
<li>
{{~ value }} </li>
{# outputs '<li>\nno spaces </li>' #}
|
小技巧
除了空格修饰符之外,Twig还有一个 spaceless
删除空白的筛选器 在HTML标记之间 :
1 2 3 4 5 6 7 | {% apply spaceless %}
<div>
<strong>foo bar</strong>
</div>
{% endapply %}
{# output will be <div><strong>foo bar</strong></div> #}
|
扩展¶
树枝可以伸展。如果您想创建自己的扩展,请阅读 Creating an Extension 章。