Twig 模板设计师指南
本文档描述了模板引擎的语法和语义,对于创建 Twig 模板的人员来说,它将是最有用的参考。
概要
模板是一个常规文本文件。它可以生成任何基于文本的格式(HTML、XML、CSV、LaTeX 等)。它没有特定的扩展名,.html
或 .xml
都可以。
模板包含变量或表达式,它们在模板求值时被替换为值,以及控制模板逻辑的 标签。
下面是一个最小的模板,说明了一些基本知识。我们将在后面详细介绍
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 循环,后者输出表达式的结果。
提示
要试验 Twig,您可以使用 Twig Playground。
第三方集成
许多 IDE 支持 Twig 的语法高亮和自动完成
- Textmate 通过 Twig bundle
- Vim 通过 vim-twig 插件
- Netbeans (7.2 版本起原生支持)
- PhpStorm (2.1 版本起原生支持)
- Eclipse 通过 Twig 插件
- Sublime Text 通过 Twig bundle
- GtkSourceView 通过 Twig 语言定义 (gedit 和其他项目使用)
- Coda 和 SubEthaEdit 通过 Twig 语法模式
- Coda 2 通过 其他 Twig 语法模式
- Komodo 和 Komodo Edit 通过 Twig 高亮/语法检查模式
- Notepad++ 通过 Notepad++ Twig Highlighter
- Emacs 通过 web-mode.el
- Atom 通过 PHP-twig for atom
- Visual Studio Code 通过 Twig pack, Modern Twig 或 Twiggy
您可能也对以下内容感兴趣
- Twig Language Server: 提供一些语言功能,如语法高亮、诊断、自动完成等。
- TwigQI: 一个扩展,可在编译期间分析您的模板中常见的错误
- TwigStan: 一个由 PHPStan 驱动的 Twig 模板静态分析器
变量
Twig 模板可以访问 PHP 应用程序提供的变量以及在模板中通过 set 标签创建的变量。这些变量可以在模板中进行操作和显示。
Twig 尝试尽可能地抽象 PHP 类型,并使用一些基本类型,这些类型受 filters
、functions
和 tests
等支持
Twig 类型 | PHP 类型 |
---|---|
字符串 | 字符串或 Stringable 对象 |
数字 | 整数或浮点数 |
布尔值 | true 或 false |
null | null |
可迭代对象 (映射) | 数组 |
可迭代对象 (序列) | 数组 |
可迭代对象 (对象) | 可迭代对象 |
对象 | 对象 |
iterable
和 object
类型公开了您可以通过点 (.
) 运算符访问的属性
1
{{ user.name }}
注意
重要的是要知道花括号 不是 变量的一部分,而是打印语句的一部分。在标签内访问变量时,请勿将花括号括在它们周围。
如果变量或属性不存在,则行为取决于 strict_variables
选项值(请参阅 环境选项)
- 当
false
时,它返回null
; - 当
true
时,它会抛出异常。
了解更多关于 点运算符 的信息。
过滤器
变量和表达式可以通过过滤器进行修改。过滤器通过管道符号 (|
) 与变量分隔。可以链接多个过滤器。一个过滤器的输出应用于下一个过滤器。
以下示例从 name
中删除所有 HTML 标签并将其转换为首字母大写
1
{{ name|striptags|title }}
接受参数的过滤器在参数周围带有括号。此示例通过逗号连接列表的元素
1
{{ list|join(', ') }}
要在代码段上应用过滤器,请使用 apply 标签将其包装起来
1 2 3
{% apply upper %}
This text becomes uppercase
{% endapply %}
转到 过滤器 页面以了解有关内置过滤器的更多信息。
警告
由于 filter
运算符具有最高的 优先级,因此在过滤更“复杂”的表达式时,请使用括号
1 2 3
{{ (1..5)|join(', ') }}
{{ ('HELLO' ~ 'FABIEN')|lower }}
函数
可以调用函数来生成内容。函数通过其名称后跟括号 (()
) 调用,并且可能带有参数。
例如,range
函数返回一个包含整数算术级数的列表
1 2 3
{% for i in range(0, 3) %}
{{ i }},
{% endfor %}
转到 函数 页面以了解有关内置函数的更多信息。
命名参数
在可以传递参数的任何地方都支持命名参数:函数、过滤器、测试、宏和点运算符参数。
3.15
宏和点运算符参数的命名参数是在 Twig 3.15 中添加的。
3.12
Twig 同时支持 =
和 :
作为参数名称和值之间的分隔符,但对 :
的支持是在 Twig 3.12 中引入的。
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
/else
)、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 %}
转到 标签 页面以了解有关内置标签的更多信息。
注释
要注释掉模板的一部分,请使用注释语法 {# ... #}
。这对于调试或为其他模板设计师或您自己添加信息很有用
1 2 3 4 5
{# note: disabled template because we no longer use this
{% for user in users %}
...
{% endfor %}
#}
3.15
Twig 3.15 中添加了内联注释。
如果您想在块、变量或注释内添加注释,请使用内联注释。它们以 #
开头,并持续到行尾
1 2 3 4 5 6 7 8 9 10 11 12 13
{{
# this is an inline comment
"Hello World"|upper
# this is an inline comment
}}
{{
{
# this is an inline comment
fruit: 'apple', # this is an inline comment
color: 'red', # this is an inline comment
}|join(', ')
}}
内联注释也可以与表达式位于同一行
1 2 3
{{
"Hello World"|upper # this is an inline comment
}}
由于内联注释持续到当前行末尾,因此以下代码不起作用,因为 }}
将成为注释的一部分
1
{{ "Hello World"|upper # this is an inline comment }}
包含其他模板
include 函数用于包含模板并将该模板的渲染内容返回到当前模板中
1
{{ include('sidebar.html.twig') }}
默认情况下,包含的模板与包含它们的模板具有相同的上下文访问权限。这意味着在主模板中定义的任何变量在包含的模板中也可用
1 2 3
{% for box in boxes %}
{{ include('render_box.html.twig') }}
{% endfor %}
包含的模板 render_box.html.twig
可以访问 box
变量。
模板的名称取决于模板加载器。例如,\Twig\Loader\FilesystemLoader
允许您通过给出文件名来访问其他模板。您可以使用斜杠访问子目录中的模板
1
{{ include('sections/articles/sidebar.html.twig') }}
此行为取决于嵌入 Twig 的应用程序。
模板继承
Twig 最强大的部分是模板继承。模板继承允许您构建一个基础“骨架”模板,其中包含您站点的所有公共元素,并定义子模板可以覆盖的 块。
从示例开始理解这个概念更容易。
让我们定义一个基本模板 base.html.twig
,它定义了一个 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="https://example.com/">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.twig" %}
{% 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
。
手动转义
如果启用了手动转义,则 您 有责任在需要时转义变量。要转义什么?来自不受信任来源的任何变量。
转义通过使用 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 允许在任何地方使用表达式。
字面量
表达式最简单的形式是字面量。字面量是 PHP 类型(如字符串、数字和数组)的表示形式。存在以下字面量
"Hello World"
:两个双引号或单引号之间的所有内容都是字符串。当您需要在模板中使用字符串时,它们很有用(例如,作为函数调用、过滤器的参数,或者只是扩展或包含模板)。- 请注意,某些字符需要转义
-
\f
:换页符\n
:换行符\r
:回车符\t
:水平制表符\v
:垂直制表符\x
:十六进制转义序列\0
到\377
:表示字符的八进制转义序列\
:反斜杠
使用单引号字符串时,单引号字符 (
'
) 需要用反斜杠 (\'
) 转义。使用双引号字符串时,双引号字符 ("
) 需要用反斜杠 (\"
) 转义。例如,如果单引号字符串前面有反斜杠 (
\
),则可以包含分隔符,例如'It\'s good'
。如果字符串包含反斜杠(例如'c:\Program Files'
),请通过将其加倍来转义它(例如'c:\\Program Files'
)。
42
/42.23
:整数和浮点数通过写下数字来创建。如果存在点,则该数字为浮点数,否则为整数。下划线可以用作数字分隔符以
提高可读性(-3_141.592_65
等同于-3141.59265
)。["first_name", "last_name"]
:序列由逗号 (,
) 分隔并用方括号 ([]
) 包裹的表达式序列定义。{"name": "Fabien"}
:映射由逗号 (,
) 分隔并用花括号 ({}
) 包裹的键和值列表定义1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
{# keys as string #} {'name': 'Fabien', 'city': 'Paris'} {# keys as names (equivalent to the previous mapping) #} {name: 'Fabien', city: 'Paris'} {# keys as integer #} {2: 'Twig', 4: 'Symfony'} {# keys can be omitted if it is the same as the variable name #} {Paris} {# is equivalent to the following #} {'Paris': Paris} {# keys as expressions (the expression must be enclosed into parentheses) #} {% set key = 'name' %} {(key): 'Fabien', (1 + 1): 2, ('ci' ~ 'ty'): 'city'}
true
/false
:true
表示真值,false
表示假值。null
:null
表示没有特定值。这是变量不存在时返回的值。none
是null
的别名。
序列和映射可以嵌套
1
{% set complex = [1, {"name": "Fabien"}] %}
提示
使用双引号或单引号字符串对性能没有影响,但 字符串插值 仅在双引号字符串中受支持。
字符串插值
字符串插值 (#{expression}
) 允许任何有效表达式出现在 双引号字符串 中。评估该表达式的结果将插入到字符串中
1 2
{{ "first #{middle} last" }}
{{ "first #{1 + 2} last" }}
提示
可以通过使用反斜杠 (\
) 转义字符串插值来忽略它们
1 2
{# outputs first #{1 + 2} last #}
{{ "first \#{1 + 2} last" }}
数学运算
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
。请注意,**
运算符是右结合的,这意味着{{ -1**0 }}
等同于{{ -(1**0) }}
而不是{{ (-1)**0 }}
。
逻辑运算
您可以使用以下运算符组合多个表达式
and
:如果左操作数和右操作数均为真,则返回 true。xor
:如果左操作数或右操作数 之一 为真,但不能两者都为真,则返回 true。or
:如果左操作数或右操作数为真,则返回 true。not
:否定语句。(expr)
:对表达式进行分组。
注意
Twig 还支持位运算符(b-and
、b-xor
和 b-or
)。
注意
运算符区分大小写。
比较运算
任何表达式中都支持以下数学比较运算符:==
、!=
、<
、>
、>=
和 <=
。
可迭代运算符
检查可迭代对象 has every
或 has some
的元素是否返回 true
,使用箭头函数。箭头函数接收可迭代对象的值作为其参数
1 2 3 4 5 6 7
{% set sizes = [34, 36, 38, 40, 42] %}
{% set hasOnlyOver38 = sizes has every v => v > 38 %}
{# hasOnlyOver38 is false #}
{% set hasOver38 = sizes has some v => v > 38 %}
{# hasOver38 is true #}
对于空的可迭代对象,has every
返回 true
,而 has some
返回 false
。
包含运算符
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]) %}
starts with
和 ends with
运算符用于检查字符串是否以给定的子字符串开头或结尾
1 2 3 4 5
{% if 'Fabien' starts with 'F' %}
{% endif %}
{% if 'Fabien' ends with 'n' %}
{% endif %}
测试运算符
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')) %}
转到 测试 页面以了解有关内置测试的更多信息。
其他运算符
以下运算符不属于任何其他类别
|
:应用过滤器。..
:基于运算符之前和之后的运算数创建序列(这是 range 函数的语法糖)1 2 3 4
{% for i in 1..5 %}{{ i }}{% endfor %} {# is equivalent to #} {% for i in range(1, 5) %}{{ i }}{% endfor %}
请注意,由于 运算符优先级规则,当将其与过滤器运算符组合时,必须使用括号
1
{{ (1..5)|join(', ') }}
~
:将所有操作数转换为字符串并将它们连接起来。{{ "Hello " ~ name ~ "!" }}
将返回(假设name
是'John'
)Hello John!
。
.
,[]
:获取变量的属性。(
.
) 运算符抽象了获取变量的属性(PHP 对象的方法、属性或常量,或 PHP 数组的项)1 2 3 4
{{ user.name }} Twig supports a specific syntax via the ``[]`` operator for accessing items on sequences and mappings, like in ``user['name']``:
在
.
之后,您可以通过用括号()
将其包装起来来使用任何表达式。一种用例是当属性包含特殊字符时(例如
-
,它将被解释为减号运算符)1 2
{# equivalent to the non-working user.first-name #} {{ user.('first-name') }}
另一种用例是当属性是“动态的”(通过变量定义)时
1 2
{{ user.(name) }} {{ user.('get' ~ name) }}
在 Twig 3.15 之前,对于之前的两个用例,请改用 attribute 函数。
Twig 通过
[]
运算符支持特定语法,用于访问序列和映射上的项1
{{ user['name'] }}
调用方法时,可以使用
()
运算符传递参数1 2 3 4
{{ html.generate_input() }} {{ html.generate_input('pwd', 'password') }} {# or using named arguments #} {{ html.generate_input(name: 'pwd', type: 'password') }}
?:
:三元运算符1 2 3
{{ result ? 'yes' : 'no' }} {{ result ?: 'no' }} is the same as {{ result ? result : 'no' }} {{ result ? 'yes' }} is the same as {{ result ? 'yes' : '' }}
??
:null 合并运算符1 2
{# returns the value of result if it is defined and not null, 'no' otherwise #} {{ result ?? 'no' }}
...
:展开运算符可用于展开序列或映射,或展开函数调用的参数1 2 3 4
{% set numbers = [1, 2, ...moreNumbers] %} {% set ratings = {'q1': 10, 'q2': 5, ...moreRatings} %} {{ 'Hello %s %s!'|format(...['Fabien', 'Potencier']) }}
3.15
对展开函数调用的参数的支持是在 Twig 3.15 中引入的。
=>
:箭头运算符允许创建函数。函数由参数(使用括号表示多个参数)和一个箭头 (=>
) 后跟要执行的表达式组成。表达式可以访问所有传递的参数。箭头函数作为过滤器、函数、测试、宏和方法调用的参数受支持。例如,内置的
map
、reduce
、sort
、filter
和find
过滤器接受箭头函数作为参数1
{{ people|map(p => p.first_name)|join(', ') }}
箭头函数可以存储在变量中
1 2 3
{% set first_name_fn = (p) => p.first_name %} {{ people|map(first_name_fn)|join(', ') }}
3.15
Twig 3.15 中添加了对函数、宏和方法调用的箭头函数支持(过滤器和测试已经受支持)。
可以使用 invoke 过滤器调用箭头函数。
3.19
invoke
过滤器已在 Twig 3.19 中添加。
运算符
Twig 使用运算符在模板中执行各种操作。理解这些运算符的优先级对于编写正确且高效的 Twig 模板至关重要。
运算符优先级规则如下,优先级最低的运算符首先列出。
优先级 | 运算符 | 类型 | 结合性 | 描述 |
---|---|---|---|---|
512 | ... |
prefix | n/a | 展开运算符 |
=> 300 | | |
infix | 左 | Twig 过滤器调用 |
( |
Twig 函数调用 | |||
. |
获取变量的属性 | |||
[ |
数组访问 | |||
500 | - |
prefix | n/a | |
+ |
||||
300 => 5 | ?? |
infix | 右 | Null 合并运算符 (a ?? b) |
250 | => |
infix | 左 | 箭头函数 (x => expr) |
200 | ** |
infix | 右 | 指数运算符 |
100 | is |
infix | 左 | Twig 测试 |
is not |
Twig 测试 | |||
60 | * |
infix | 左 | |
/ |
||||
// |
向下取整除法 | |||
% |
||||
50 => 70 | not |
prefix | n/a | |
40 => 27 | ~ |
infix | 左 | |
30 | + |
infix | 左 | |
- |
||||
25 | .. |
infix | 左 | |
20 | == |
infix | 左 | |
!= |
||||
<=> |
||||
< |
||||
> |
||||
>= |
||||
<= |
||||
not in |
||||
in |
||||
matches |
||||
starts with |
||||
ends with |
||||
has some |
||||
has every |
||||
18 | b-and |
infix | 左 | |
17 | b-xor |
infix | 左 | |
16 | b-or |
infix | 左 | |
15 | and |
infix | 左 | |
12 | xor |
infix | 左 | |
10 | or |
infix | 左 | |
5 | ?: |
infix | 右 | Elvis 运算符 (a ?: b) |
?: |
Elvis 运算符 (a ?: b) | |||
0 | ( |
prefix | n/a | 显式分组表达式 (a) |
literal |
字面量值(布尔值、字符串、数字、序列、映射等) | |||
? |
infix | 左 | 条件运算符 (a ? b : c) |
当优先级在 4.0 中更改时,新优先级由箭头 =>
指示。
这是 Twig 4.0 的相同表格,其中调整了优先级
优先级 | 运算符 | 类型 | 结合性 | 描述 |
---|---|---|---|---|
512 | ... |
prefix | n/a | 展开运算符 |
( |
infix | 左 | Twig 函数调用 | |
. |
获取变量的属性 | |||
[ |
数组访问 | |||
500 | - |
prefix | n/a | |
+ |
||||
300 | | |
infix | 左 | Twig 过滤器调用 |
250 | => |
infix | 左 | 箭头函数 (x => expr) |
200 | ** |
infix | 右 | 指数运算符 |
100 | is |
infix | 左 | Twig 测试 |
is not |
Twig 测试 | |||
70 | not |
prefix | n/a | |
60 | * |
infix | 左 | |
/ |
||||
// |
向下取整除法 | |||
% |
||||
30 | + |
infix | 左 | |
- |
||||
27 | ~ |
infix | 左 | |
25 | .. |
infix | 左 | |
20 | == |
infix | 左 | |
!= |
||||
<=> |
||||
< |
||||
> |
||||
>= |
||||
<= |
||||
not in |
||||
in |
||||
matches |
||||
starts with |
||||
ends with |
||||
has some |
||||
has every |
||||
18 | b-and |
infix | 左 | |
17 | b-xor |
infix | 左 | |
16 | b-or |
infix | 左 | |
15 | and |
infix | 左 | |
12 | xor |
infix | 左 | |
10 | or |
infix | 左 | |
5 | ?? |
infix | 右 | Null 合并运算符 (a ?? b) |
?: |
Elvis 运算符 (a ?: b) | |||
?: |
Elvis 运算符 (a ?: b) | |||
0 | ( |
prefix | n/a | 显式分组表达式 (a) |
literal |
字面量值(布尔值、字符串、数字、序列、映射等) | |||
? |
infix | 左 | 条件运算符 (a ? b : c) |
在不使用任何括号的情况下,运算符优先级规则用于确定如何将代码转换为 PHP
1 2 3
{{ 6 b-and 2 or 6 b-and 16 }}
{# it is converted to the following PHP code: (6 & 2) || (6 & 16) #}
通过使用括号显式分组表达式来更改默认优先级
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)。模板引擎不会进一步修改空白字符,因此每个空白字符(空格、制表符、换行符等)都会保持不变地返回。
你也可以在每个标签级别控制空白字符。通过在标签上使用空白字符控制修饰符,你可以修剪前导或尾随空白字符。
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>' #}