Volt:模板引擎
最后更新于:2022-04-02 05:15:02
[TOC]
# Volt:模板引擎
Volt是一种用C语言编写的超快速且设计友好的模板语言。它为您提供了一组帮助程序,以便以简单的方式编写视图。Volt与Phalcon的其他组件高度集成,就像您可以将其用作应用程序中的独立组件一样。
![](https://docs.phalconphp.com/images/content/volt.jpg)
Volt的灵感来自最初由[Armin Ronacher](https://github.com/mitsuhiko)创作的[Jinja](http://jinja.pocoo.org/)。因此,许多开发人员将使用与类似模板引擎相同的语法在熟悉的领域。Volt的语法和功能已经通过更多元素得到增强,当然还有开发人员在使用Phalcon时习惯的性能。
## 介绍
Volt视图被编译为纯PHP代码,因此基本上他们省去了手动编写PHP代码的工作:
```twig
{# app/views/products/show.volt #}
{% block last_products %}
{% for product in products %}
* Name: {{ product.name|e }}
{% if product.status === 'Active' %}
Price: {{ product.price + product.taxes/100 }}
{% endif %}
{% endfor %}
{% endblock %}
```
## 激活Volt
与其他模板引擎一样,您可以在视图组件中注册Volt,使用新扩展或重用标准`.phtml`:
```php
set(
'voltService',
function ($view, $di) {
$volt = new Volt($view, $di);
$volt->setOptions(
[
'compiledPath' => '../app/compiled-templates/',
'compiledExtension' => '.compiled',
]
);
return $volt;
}
);
// Register Volt as template engine
$di->set(
'view',
function () {
$view = new View();
$view->setViewsDir('../app/views/');
$view->registerEngines(
[
'.volt' => 'voltService',
]
);
return $view;
}
);
```
使用标准的`.phtml`扩展名:
```php
registerEngines(
[
'.phtml' => 'voltService',
]
);
```
您无需在DI中指定Volt服务;你也可以使用Volt引擎的默认设置:
```php
registerEngines(
[
'.volt' => Phalcon\Mvc\View\Engine\Volt::class,
]
);
```
如果您不想将Volt重用为服务,则可以传递匿名函数来注册引擎而不是服务名称:
```php
set(
'view',
function () {
$view = new View();
$view->setViewsDir('../app/views/');
$view->registerEngines(
[
'.volt' => function ($view, $di) {
$volt = new Volt($view, $di);
// Set some options here
return $volt;
}
]
);
return $view;
}
);
```
Volt提供以下选项:
| 选项 | 描述 | 默认 |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------- | ------- |
| `autoescape` | 启用HTML的全局自动视图 | `false` |
| `compileAlways` | 如果模板必须在每个请求中编译或仅在更改时,请告诉Volt | `false` |
| `compiledExtension` | 附加到编译的PHP文件的附加扩展 | `.php` |
| `compiledPath` | 一个可写路径,将放置已编译的PHP模板 | `./` |
| `compiledSeparator` | Volt用这个分隔符替换目录分隔符/和\,以便在编译目录中创建单个文件| `%%` |
| `prefix` | 允许在编译路径中为模板添加前缀 | `null` |
| `stat` | Phalcon是否必须检查模板文件与其编译路径之间是否存在差异 | `true` |
根据上述选项生成编译路径,如果开发人员希望完全自由地定义编译路径,则可以使用匿名函数生成它,此函数接收视图目录中模板的相对路径。以下示例显示如何动态更改编译路径:
```php
setOptions(
[
'compiledPath' => function ($templatePath) {
return $templatePath . '.php';
}
]
);
// Recursively create the same structure in another directory
$volt->setOptions(
[
'compiledPath' => function ($templatePath) {
$dirName = dirname($templatePath);
if (!is_dir('cache/' . $dirName)) {
mkdir('cache/' . $dirName , 0777 , true);
}
return 'cache/' . $dirName . '/'. $templatePath . '.php';
}
]
);
```
## 基本用法
视图由Volt代码,PHP和HTML组成。一组特殊分隔符可用于进入伏特模式。`{%...%}`用于执行诸如for循环或赋值和`{{...}}`之类的语句,将表达式的结果打印到模板。
下面是一个最小的模板,它说明了一些基础知识:
```twig
{# app/views/posts/show.phtml #}
{{ title }} - An example blog
{% if show_navigation %}
{% endif %}
`)。使用PHP函数[nl2br](http://php.net/manual/en/function.nl2br.php)| | `right_trim` | 将[rtrim](http://php.net/manual/en/function.rtrim.php) PHP函数应用于该值。删除多余的空格 | | `sort` | 使用PHP函数asort [asort](http://php.net/manual/en/function.asort.php) 对数组进行排序 | | `stripslashes` | 将[stripslashes](http://php.net/manual/en/function.stripslashes.php) PHP函数应用于该值。删除转义的引号 | | `striptags` | 将[strip_tags](http://php.net/manual/en/function.strip-tags.php) PHP函数应用于值。删除HTML标记 | | `trim` | 将[trim](http://php.net/manual/en/function.trim.php)PHP函数应用于该值。删除多余的空格 | | `upper` | 将字符串的大小写更改为大写 | | `url_encode` | 将[urlencode](http://php.net/manual/en/function.urlencode.php) PHP函数应用于该值 | 例子: ```twig {# e or escape filter #} {{ 'Hello
{% endif %}
{% endfor %}
```
## 赋值
可以使用指令'set'在模板中更改变量:
```twig
{% set fruits = ['Apple', 'Banana', 'Orange'] %}
{% set name = robot.name %}
```
同一指令允许多次分配:
```twig
{% set fruits = ['Apple', 'Banana', 'Orange'], name = robot.name, active = true %}
```
此外,您可以使用复合赋值运算符:
```twig
{% set price += 100.00 %}
{% set age *= 5 %}
```
以下操作可用:
| 操作符 | 描述 |
| -------- | ------------------------- |
| `=` | 标准赋值 |
| `+=` | 加等赋值 |
| `-=` | 减等赋值 |
| `*=` | 乘等赋值 |
| `/=` | 除等赋值 |
## 表达式
Volt提供了一组基本的表达式支持,包括文字和常用运算符。可以使用`{{`和`}}`分隔符评估和打印表达式:
```twig
{{ (1 + 1) * 2 }}
```
如果需要在不打印的情况下计算表达式,则可以使用`do`语句:
```twig
{% do (1 + 1) * 2 %}
```
### 字面量
支持以下字面量:
| Filter | 描述 |
| -------------------- | ------------------------------------------------------------------ |
| `'this is a string'` |双引号或单引号之间的文本作为字符串处理 |
| `100.25` | 带小数部分的数字作为双精度/浮点数处理 |
| `100` |没有小数部分的数字作为整数处理 |
| `false` | 常量'false'是布尔值false |
| `true` | 常量'true'是布尔值true |
| `null` | 常量'null'是Null值 |
### 数组
无论您使用的是PHP 5.3还是 >= 5.4,您都可以通过在方括号中包含值列表来创建数组:
```twig
{# Simple array #}
{{ ['Apple', 'Banana', 'Orange'] }}
{# Other simple array #}
{{ ['Apple', 1, 2.5, false, null] }}
{# Multi-Dimensional array #}
{{ [[1, 2], [3, 4], [5, 6]] }}
{# Hash-style array #}
{{ ['first': 1, 'second': 4/2, 'third': '3'] }}
```
大括号也可用于定义数组或哈希:
```twig
{% set myArray = {'Apple', 'Banana', 'Orange'} %}
{% set myHash = {'first': 1, 'second': 4/2, 'third': '3'} %}
```
### 数学运算
您可以使用以下运算符在模板中进行计算:
| 操作符 | 描述 |
|:--------:| ----------------------------------------------------------------------- |
| `+` | 执行加法操作 `{{ 2 + 3 }}` 返回 5 |
| `-` | 执行减法操作 `{{ 2 - 3 }}` 返回 -1 |
| `*` | 执行乘法操作 `{{ 2 * 3 }}` 返回 6 |
| `/` | 执行除法操作 `{{ 10 / 2 }}` 返回 5 |
| `%` | 执行取余操作 `{{ 10 % 3 }}` 返回 1 |
### 比较运算
以下比较运算符可用:
| 操作符 | 描述 |
|:----------:| ----------------------------------------------------------------- |
| `==` | 检查两个操作数是否相等 |
| `!=` | 检查两个操作数是否不相等 |
| `<>` | 检查两个操作数是否不相等 |
| `>` | 检查左操作数是否大于右操作数 |
| `<` | 检查左操作数是否小于右操作数 |
| `<=` | 检查左操作数是否小于等于于右操作数 |
| `>=` | 检查左操作数是否大于等于右操作数 |
| `===` | 检查两个操作数是否全等 |
| `!==` | 检查两个操作数是否不全等 |
### 逻辑运算
逻辑运算符在`if`表达式求值中用于组合多个测试:
| 操作符 | 描述 |
|:----------:| ----------------------------------------------------------------- |
| `or` | 逻辑或 |
| `and` | 逻辑与 |
| `not` | 逻辑非 |
| `( expr )` | 括号组表达式 |
### 其他操作符
其他操作符可以看到以下操作符:
| 操作符 | 描述 |
| ----------------- | ------------------------------------------------------------------------------- |
| `~` | 连接两个操作数 `{{ 'hello ' ~ 'world' }}` |
| `|` | 在左侧的右操作数中应用过滤器`{{ 'hello'|uppercase }}` |
| `..` | 创建一个范围 `{{ 'a'..'z' }}` `{{ 1..10 }}` |
| `is` | 与==(等于)相同,也执行检测 |
| `in` | 检测一个表达式是否被另一个表达式包含在内 `if 'a' in 'abc'` |
| `is not` | 与!=相同(不等于) |
| `'a' ? 'b' : 'c'` | 三元运算符。与PHP三元运算符相同 |
| `++` | 递增一个值 |
| `--` | 递减一个值 |
以下示例显示如何使用运算符:
```twig
{% set robots = ['Voltron', 'Astro Boy', 'Terminator', 'C3PO'] %}
{% for index in 0..robots|length %}
{% if robots[index] is defined %}
{{ 'Name: ' ~ robots[index] }}
{% endif %}
{% endfor %}
```
## 检测
检测可用于检测变量是否具有有效的预期值。运算符`is` 用于执行检测:
```twig
{% set robots = ['1': 'Voltron', '2': 'Astro Boy', '3': 'Terminator', '4': 'C3PO'] %}
{% for position, name in robots %}
{% if position is odd %}
{{ name }}
{% endif %}
{% endfor %}
```
Volt提供以下内置检测:
| 检测 | 描述 |
| ------------- | -------------------------------------------------------------------- |
| `defined` | 检查是否定义了变量(`isset()`) |
| `divisibleby` | 检查值是否可以被其他值整除 |
| `empty` | 检查变量是否为空 |
| `even` | 检查数值是否是偶数 |
| `iterable` | 检查值是否可迭代。可以通过'for'语句遍历 |
| `numeric` | 检查值是否为数字 |
| `odd` | 检查数值是否是奇数 |
| `sameas` | 检查值是否与其他值相同 |
| `scalar` | 检查值是否为标量(不是数组或对象) |
| `type` | 检查值是否为指定类型 |
更多示例:
```twig
{% if robot is defined %}
The robot variable is defined
{% endif %}
{% if robot is empty %}
The robot is null or isn't defined
{% endif %}
{% for key, name in [1: 'Voltron', 2: 'Astroy Boy', 3: 'Bender'] %}
{% if key is even %}
{{ name }}
{% endif %}
{% endfor %}
{% for key, name in [1: 'Voltron', 2: 'Astroy Boy', 3: 'Bender'] %}
{% if key is odd %}
{{ name }}
{% endif %}
{% endfor %}
{% for key, name in [1: 'Voltron', 2: 'Astroy Boy', 'third': 'Bender'] %}
{% if key is numeric %}
{{ name }}
{% endif %}
{% endfor %}
{% set robots = [1: 'Voltron', 2: 'Astroy Boy'] %}
{% if robots is iterable %}
{% for robot in robots %}
...
{% endfor %}
{% endif %}
{% set world = 'hello' %}
{% if world is sameas('hello') %}
{{ 'it's hello' }}
{% endif %}
{% set external = false %}
{% if external is type('boolean') %}
{{ 'external is false or true' }}
{% endif %}
```
## 宏
宏可用于在模板中重用逻辑,它们充当PHP函数,可以接收参数并返回值:
```twig
{# Macro 'display a list of links to related topics' #}
{%- macro related_bar(related_links) %}
{% block title %}{% endblock %} - My Webpage
Index - My Webpage
```
### 多重继承
扩展模板可以扩展其他模板。以下示例说明了这一点:
```twig
{# main.volt #}
Title
{% block content %}{% endblock %}
```
模板 `layout.volt` 继承 `main.volt`
```twig
{# layout.volt #}
{% extends 'main.volt' %}
{% block content %}
Title
';
{{ post.title }}
{{ post.content }}
```
使用`Phalcon\Mvc\View` 可以将变量从控制器传递到视图。在上面的例子中,四个变量被传递给视图:`show_navigation`,`menu`,`title`和`post`:
```php
view->show_navigation = true;
$this->view->menu = $menu;
$this->view->title = $post->title;
$this->view->post = $post;
// Or...
$this->view->setVar('show_navigation', true);
$this->view->setVar('menu', $menu);
$this->view->setVar('title', $post->title);
$this->view->setVar('post', $post);
}
}
```
## 变量
对象变量可能具有可使用以下语法访问的属性:`foo.bar`。如果要传递数组,则必须使用方括号语法:`foo ['bar']`
```twig
{{ post.title }} {# for $post->title #}
{{ post['title'] }} {# for $post['title'] #}
```
## 过滤
可以使用过滤器格式化或修改变量。管道操作`|`用于将过滤器应用于变量:
```twig
{{ post.title|e }}
{{ post.content|striptags }}
{{ name|capitalize|trim }}
```
以下是Volt中可用的内置过滤器列表:
| 过滤 | 描述 |
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| `abs` | 将[abs](http://php.net/manual/en/function.abs.php) PHP函数应用于值。 |
| `capitalize` | 通过将[ucwords](http://php.net/manual/en/function.ucwords.php) PHP函数应用于值来大写字符串 |
| `convert_encoding` | 将字符串从一个字符集转换为另一个字符集 |
| `default` | 如果计算的表达式为空(未设置或计算为false值),则设置默认值 |
| `e` | 将 `Phalcon\Escaper->escapeHtml()` 应用于该值 |
| `escape` | 将 `Phalcon\Escaper->escapeHtml()` 应用于该值 |
| `escape_attr` | 将 `Phalcon\Escaper->escapeHtmlAttr()` 应用于该值 |
| `escape_css` | 将 `Phalcon\Escaper->escapeCss()` 应用于该值 |
| `escape_js` | 将 `Phalcon\Escaper->escapeJs()` 应用于该值 |
| `format` | 使用 [sprintf](http://php.net/manual/en/function.sprintf.php) 格式化字符串。 |
| `json_encode` | 将值转换为其[JSON](http://php.net/manual/en/function.json-encode.php)表示形式 |
| `json_decode` | 将值从其[JSON](http://php.net/manual/en/function.json-encode.php)表示转换为PHP表示 |
| `join` | 使用分隔符[join](http://php.net/manual/en/function.join.php)来连接数组部件 |
| `keys` | 使用[array_keys](http://php.net/manual/en/function.array-keys.php)返回数组键 |
| `left_trim` | 将[ltrim](http://php.net/manual/en/function.ltrim.php) PHP函数应用于该值。删除多余的空格 |
| `length` | 计算字符串长度或数组或对象中的项目数 |
| `lower` | 将字符串的大小写更改为小写 |
| `nl2br` | 通过换行符 `\n`更改换行符(``)。使用PHP函数[nl2br](http://php.net/manual/en/function.nl2br.php)| | `right_trim` | 将[rtrim](http://php.net/manual/en/function.rtrim.php) PHP函数应用于该值。删除多余的空格 | | `sort` | 使用PHP函数asort [asort](http://php.net/manual/en/function.asort.php) 对数组进行排序 | | `stripslashes` | 将[stripslashes](http://php.net/manual/en/function.stripslashes.php) PHP函数应用于该值。删除转义的引号 | | `striptags` | 将[strip_tags](http://php.net/manual/en/function.strip-tags.php) PHP函数应用于值。删除HTML标记 | | `trim` | 将[trim](http://php.net/manual/en/function.trim.php)PHP函数应用于该值。删除多余的空格 | | `upper` | 将字符串的大小写更改为大写 | | `url_encode` | 将[urlencode](http://php.net/manual/en/function.urlencode.php) PHP函数应用于该值 | 例子: ```twig {# e or escape filter #} {{ '
Hello'|e }}
{{ 'Hello'|escape }}
{# trim filter #}
{{ ' hello '|trim }}
{# striptags filter #}
{{ 'Hello'|striptags }}
{# slashes filter #}
{{ ''this is a string''|slashes }}
{# stripslashes filter #}
{{ '\'this is a string\''|stripslashes }}
{# capitalize filter #}
{{ 'hello'|capitalize }}
{# lower filter #}
{{ 'HELLO'|lower }}
{# upper filter #}
{{ 'hello'|upper }}
{# length filter #}
{{ 'robots'|length }}
{{ [1, 2, 3]|length }}
{# nl2br filter #}
{{ 'some\ntext'|nl2br }}
{# sort filter #}
{% set sorted = [3, 1, 2]|sort %}
{# keys filter #}
{% set keys = ['first': 1, 'second': 2, 'third': 3]|keys %}
{# join filter #}
{% set joined = 'a'..'z'|join(',') %}
{# format filter #}
{{ 'My real name is %s'|format(name) }}
{# json_encode filter #}
{% set encoded = robots|json_encode %}
{# json_decode filter #}
{% set decoded = '{'one':1,'two':2,'three':3}'|json_decode %}
{# url_encode filter #}
{{ post.permanent_link|url_encode }}
{# convert_encoding filter #}
{{ 'désolé'|convert_encoding('utf8', 'latin1') }}
```
## 注释
也可以使用 `{# ... #}` 分隔符将注释添加到模板中。其中的所有文本都在最终输出中被忽略:
```twig
{# note: this is a comment
{% set price = 100; %}
#}
```
## 控制结构列表
Volt提供了一组基本但功能强大的控件结构,可用于模板:
### For
循环遍历序列中的每个项目。以下示例显示如何遍历一组“robots”并打印他/她的名字:
```twig
Robots
{% for robot in robots %}
-
{{ robot.name|e }}
{% endfor %}
```
for循环也可以嵌套:
```twig
Robots
{% for robot in robots %}
{% for part in robot.parts %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% endfor %}
{% endfor %}
```
您可以使用以下语法获取PHP副本中的元素`keys`:
```twig
{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}
{% for name, value in numbers %}
Name: {{ name }} Value: {{ value }}
{% endfor %}
```
可以选择设置`if`判断:
```twig
{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}
{% for value in numbers if value < 2 %}
Value: {{ value }}
{% endfor %}
{% for name, value in numbers if name !== 'two' %}
Name: {{ name }} Value: {{ value }}
{% endfor %}
```
如果在`for`中定义了`else`,则在迭代器中的表达式导致零迭代时将执行:
```twig
Robots
{% for robot in robots %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% else %}
There are no robots to show
{% endfor %}
```
替代语法:
```twig
Robots
{% for robot in robots %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% elsefor %}
There are no robots to show
{% endfor %}
```
### 循环控制
`break` 和 `continue` 语句可用于退出循环或强制当前块中的迭代:
```twig
{# skip the even robots #}
{% for index, robot in robots %}
{% if index is even %}
{% continue %}
{% endif %}
...
{% endfor %}
```
```twig
{# exit the foreach on the first even robot #}
{% for index, robot in robots %}
{% if index is even %}
{% break %}
{% endif %}
...
{% endfor %}
```
### If
作为PHP,`if`语句检查表达式是否被评估为true或false:
```twig
Cyborg Robots
{% for robot in robots %}
{% if robot.type === 'cyborg' %}
- {{ robot.name|e }}
{% endif %}
{% endfor %}
```
else子句也支持:
```twig
Robots
{% for robot in robots %}
{% if robot.type === 'cyborg' %}
- {{ robot.name|e }}
{% else %}
- {{ robot.name|e }} (not a cyborg)
{% endif %}
{% endfor %}
```
`elseif`控制流结构可以与`if`一起使用来`switch`开关块:
```twig
{% if robot.type === 'cyborg' %}
Robot is a cyborg
{% elseif robot.type === 'virtual' %}
Robot is virtual
{% elseif robot.type === 'mechanical' %}
Robot is mechanical
{% endif %}
```
### Switch
`if`语句的替代方法是`switch`,允许您在应用程序中创建逻辑执行路径:
```twig
{% switch foo %}
{% case 0 %}
{% case 1 %}
{% case 2 %}
"foo" is less than 3 but not negative
{% break %}
{% case 3 %}
"foo" is 3
{% break %}
{% default %}
"foo" is {{ foo }}
{% endswitch %}
```
`switch`语句执行语句,因此在某些情况下`break`语句是必需的。`switch`语句和第一个`case` 之间的任何输出(包括空格)都将导致语法错误。因此可以清除空行和空格以减少此处的错误数量 [看这里](http://php.net/control-structures.alternative-syntax)。
#### `case` 不带 `switch`
```twig
{% case EXPRESSION %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: Unexpected CASE`:意外的CASE。
#### `switch` 不带 `endswitch`
```twig
{% switch EXPRESSION %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: Syntax error, unexpected EOF in ..., there is a 'switch' block without 'endswitch'`:语法错误,意外的EOF在......中,有一个'switch'块没有'endswitch'。
#### `default` 不带 `switch`
```twig
{% default %}
```
不会抛出错误,因为`default`是过滤器的保留字像`{{ EXPRESSION | default(VALUE) }}`但在这种情况下,表达式只会输出一个空的字符''。
#### 嵌套 `switch`
```twig
{% switch EXPRESSION %}
{% switch EXPRESSION %}
{% endswitch %}
{% endswitch %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: A nested switch detected. There is no nested switch-case statements support in ... on line ...`:检测到嵌套switch。在行...不支持嵌套的switch-case语句...
#### `switch` 不带表达式
```twig
{% switch %}
{% case EXPRESSION %}
{% break %}
{% endswitch %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: Syntax error, unexpected token %} in ... on line ...`:语法错误,意外的令牌%}在......在行...
### 循环上下文
一个特殊的变量可用于`for`循环内部,为您提供有关的信息
| 变量 | 描述 |
| ---------------- | ------------------------------------------------------------- |
| `loop.index` | 循环的当前迭代。(1索引) |
| `loop.index0` | 循环的当前迭代。(0索引) |
| `loop.revindex` | 循环结束时的迭代次数(1索引) |
| `loop.revindex0` | 循环结束时的迭代次数(0索引) |
| `loop.first` | 如果在第一次迭代中为true。 |
| `loop.last` | 如果在最后一次迭代中为true。 |
| `loop.length` | 要迭代的项目数 |
例子:
```twig
{% for robot in robots %}
{% if loop.first %}
Hello'|escape }}
{# trim filter #}
{{ ' hello '|trim }}
{# striptags filter #}
{{ 'Hello'|striptags }}
{# slashes filter #}
{{ ''this is a string''|slashes }}
{# stripslashes filter #}
{{ '\'this is a string\''|stripslashes }}
{# capitalize filter #}
{{ 'hello'|capitalize }}
{# lower filter #}
{{ 'HELLO'|lower }}
{# upper filter #}
{{ 'hello'|upper }}
{# length filter #}
{{ 'robots'|length }}
{{ [1, 2, 3]|length }}
{# nl2br filter #}
{{ 'some\ntext'|nl2br }}
{# sort filter #}
{% set sorted = [3, 1, 2]|sort %}
{# keys filter #}
{% set keys = ['first': 1, 'second': 2, 'third': 3]|keys %}
{# join filter #}
{% set joined = 'a'..'z'|join(',') %}
{# format filter #}
{{ 'My real name is %s'|format(name) }}
{# json_encode filter #}
{% set encoded = robots|json_encode %}
{# json_decode filter #}
{% set decoded = '{'one':1,'two':2,'three':3}'|json_decode %}
{# url_encode filter #}
{{ post.permanent_link|url_encode }}
{# convert_encoding filter #}
{{ 'désolé'|convert_encoding('utf8', 'latin1') }}
```
## 注释
也可以使用 `{# ... #}` 分隔符将注释添加到模板中。其中的所有文本都在最终输出中被忽略:
```twig
{# note: this is a comment
{% set price = 100; %}
#}
```
## 控制结构列表
Volt提供了一组基本但功能强大的控件结构,可用于模板:
### For
循环遍历序列中的每个项目。以下示例显示如何遍历一组“robots”并打印他/她的名字:
```twig
Robots
{% for robot in robots %}
-
{{ robot.name|e }}
{% endfor %}
```
for循环也可以嵌套:
```twig
Robots
{% for robot in robots %}
{% for part in robot.parts %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% endfor %}
{% endfor %}
```
您可以使用以下语法获取PHP副本中的元素`keys`:
```twig
{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}
{% for name, value in numbers %}
Name: {{ name }} Value: {{ value }}
{% endfor %}
```
可以选择设置`if`判断:
```twig
{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}
{% for value in numbers if value < 2 %}
Value: {{ value }}
{% endfor %}
{% for name, value in numbers if name !== 'two' %}
Name: {{ name }} Value: {{ value }}
{% endfor %}
```
如果在`for`中定义了`else`,则在迭代器中的表达式导致零迭代时将执行:
```twig
Robots
{% for robot in robots %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% else %}
There are no robots to show
{% endfor %}
```
替代语法:
```twig
Robots
{% for robot in robots %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% elsefor %}
There are no robots to show
{% endfor %}
```
### 循环控制
`break` 和 `continue` 语句可用于退出循环或强制当前块中的迭代:
```twig
{# skip the even robots #}
{% for index, robot in robots %}
{% if index is even %}
{% continue %}
{% endif %}
...
{% endfor %}
```
```twig
{# exit the foreach on the first even robot #}
{% for index, robot in robots %}
{% if index is even %}
{% break %}
{% endif %}
...
{% endfor %}
```
### If
作为PHP,`if`语句检查表达式是否被评估为true或false:
```twig
Cyborg Robots
{% for robot in robots %}
{% if robot.type === 'cyborg' %}
- {{ robot.name|e }}
{% endif %}
{% endfor %}
```
else子句也支持:
```twig
Robots
{% for robot in robots %}
{% if robot.type === 'cyborg' %}
- {{ robot.name|e }}
{% else %}
- {{ robot.name|e }} (not a cyborg)
{% endif %}
{% endfor %}
```
`elseif`控制流结构可以与`if`一起使用来`switch`开关块:
```twig
{% if robot.type === 'cyborg' %}
Robot is a cyborg
{% elseif robot.type === 'virtual' %}
Robot is virtual
{% elseif robot.type === 'mechanical' %}
Robot is mechanical
{% endif %}
```
### Switch
`if`语句的替代方法是`switch`,允许您在应用程序中创建逻辑执行路径:
```twig
{% switch foo %}
{% case 0 %}
{% case 1 %}
{% case 2 %}
"foo" is less than 3 but not negative
{% break %}
{% case 3 %}
"foo" is 3
{% break %}
{% default %}
"foo" is {{ foo }}
{% endswitch %}
```
`switch`语句执行语句,因此在某些情况下`break`语句是必需的。`switch`语句和第一个`case` 之间的任何输出(包括空格)都将导致语法错误。因此可以清除空行和空格以减少此处的错误数量 [看这里](http://php.net/control-structures.alternative-syntax)。
#### `case` 不带 `switch`
```twig
{% case EXPRESSION %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: Unexpected CASE`:意外的CASE。
#### `switch` 不带 `endswitch`
```twig
{% switch EXPRESSION %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: Syntax error, unexpected EOF in ..., there is a 'switch' block without 'endswitch'`:语法错误,意外的EOF在......中,有一个'switch'块没有'endswitch'。
#### `default` 不带 `switch`
```twig
{% default %}
```
不会抛出错误,因为`default`是过滤器的保留字像`{{ EXPRESSION | default(VALUE) }}`但在这种情况下,表达式只会输出一个空的字符''。
#### 嵌套 `switch`
```twig
{% switch EXPRESSION %}
{% switch EXPRESSION %}
{% endswitch %}
{% endswitch %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: A nested switch detected. There is no nested switch-case statements support in ... on line ...`:检测到嵌套switch。在行...不支持嵌套的switch-case语句...
#### `switch` 不带表达式
```twig
{% switch %}
{% case EXPRESSION %}
{% break %}
{% endswitch %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: Syntax error, unexpected token %} in ... on line ...`:语法错误,意外的令牌%}在......在行...
### 循环上下文
一个特殊的变量可用于`for`循环内部,为您提供有关的信息
| 变量 | 描述 |
| ---------------- | ------------------------------------------------------------- |
| `loop.index` | 循环的当前迭代。(1索引) |
| `loop.index0` | 循环的当前迭代。(0索引) |
| `loop.revindex` | 循环结束时的迭代次数(1索引) |
| `loop.revindex0` | 循环结束时的迭代次数(0索引) |
| `loop.first` | 如果在第一次迭代中为true。 |
| `loop.last` | 如果在最后一次迭代中为true。 |
| `loop.length` | 要迭代的项目数 |
例子:
```twig
{% for robot in robots %}
{% if loop.first %}
Hello'|striptags }}
{# slashes filter #}
{{ ''this is a string''|slashes }}
{# stripslashes filter #}
{{ '\'this is a string\''|stripslashes }}
{# capitalize filter #}
{{ 'hello'|capitalize }}
{# lower filter #}
{{ 'HELLO'|lower }}
{# upper filter #}
{{ 'hello'|upper }}
{# length filter #}
{{ 'robots'|length }}
{{ [1, 2, 3]|length }}
{# nl2br filter #}
{{ 'some\ntext'|nl2br }}
{# sort filter #}
{% set sorted = [3, 1, 2]|sort %}
{# keys filter #}
{% set keys = ['first': 1, 'second': 2, 'third': 3]|keys %}
{# join filter #}
{% set joined = 'a'..'z'|join(',') %}
{# format filter #}
{{ 'My real name is %s'|format(name) }}
{# json_encode filter #}
{% set encoded = robots|json_encode %}
{# json_decode filter #}
{% set decoded = '{'one':1,'two':2,'three':3}'|json_decode %}
{# url_encode filter #}
{{ post.permanent_link|url_encode }}
{# convert_encoding filter #}
{{ 'désolé'|convert_encoding('utf8', 'latin1') }}
```
## 注释
也可以使用 `{# ... #}` 分隔符将注释添加到模板中。其中的所有文本都在最终输出中被忽略:
```twig
{# note: this is a comment
{% set price = 100; %}
#}
```
## 控制结构列表
Volt提供了一组基本但功能强大的控件结构,可用于模板:
### For
循环遍历序列中的每个项目。以下示例显示如何遍历一组“robots”并打印他/她的名字:
```twig
Robots
{% for robot in robots %}
-
{{ robot.name|e }}
{% endfor %}
```
for循环也可以嵌套:
```twig
Robots
{% for robot in robots %}
{% for part in robot.parts %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% endfor %}
{% endfor %}
```
您可以使用以下语法获取PHP副本中的元素`keys`:
```twig
{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}
{% for name, value in numbers %}
Name: {{ name }} Value: {{ value }}
{% endfor %}
```
可以选择设置`if`判断:
```twig
{% set numbers = ['one': 1, 'two': 2, 'three': 3] %}
{% for value in numbers if value < 2 %}
Value: {{ value }}
{% endfor %}
{% for name, value in numbers if name !== 'two' %}
Name: {{ name }} Value: {{ value }}
{% endfor %}
```
如果在`for`中定义了`else`,则在迭代器中的表达式导致零迭代时将执行:
```twig
Robots
{% for robot in robots %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% else %}
There are no robots to show
{% endfor %}
```
替代语法:
```twig
Robots
{% for robot in robots %}
Robot: {{ robot.name|e }} Part: {{ part.name|e }}
{% elsefor %}
There are no robots to show
{% endfor %}
```
### 循环控制
`break` 和 `continue` 语句可用于退出循环或强制当前块中的迭代:
```twig
{# skip the even robots #}
{% for index, robot in robots %}
{% if index is even %}
{% continue %}
{% endif %}
...
{% endfor %}
```
```twig
{# exit the foreach on the first even robot #}
{% for index, robot in robots %}
{% if index is even %}
{% break %}
{% endif %}
...
{% endfor %}
```
### If
作为PHP,`if`语句检查表达式是否被评估为true或false:
```twig
Cyborg Robots
{% for robot in robots %}
{% if robot.type === 'cyborg' %}
- {{ robot.name|e }}
{% endif %}
{% endfor %}
```
else子句也支持:
```twig
Robots
{% for robot in robots %}
{% if robot.type === 'cyborg' %}
- {{ robot.name|e }}
{% else %}
- {{ robot.name|e }} (not a cyborg)
{% endif %}
{% endfor %}
```
`elseif`控制流结构可以与`if`一起使用来`switch`开关块:
```twig
{% if robot.type === 'cyborg' %}
Robot is a cyborg
{% elseif robot.type === 'virtual' %}
Robot is virtual
{% elseif robot.type === 'mechanical' %}
Robot is mechanical
{% endif %}
```
### Switch
`if`语句的替代方法是`switch`,允许您在应用程序中创建逻辑执行路径:
```twig
{% switch foo %}
{% case 0 %}
{% case 1 %}
{% case 2 %}
"foo" is less than 3 but not negative
{% break %}
{% case 3 %}
"foo" is 3
{% break %}
{% default %}
"foo" is {{ foo }}
{% endswitch %}
```
`switch`语句执行语句,因此在某些情况下`break`语句是必需的。`switch`语句和第一个`case` 之间的任何输出(包括空格)都将导致语法错误。因此可以清除空行和空格以减少此处的错误数量 [看这里](http://php.net/control-structures.alternative-syntax)。
#### `case` 不带 `switch`
```twig
{% case EXPRESSION %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: Unexpected CASE`:意外的CASE。
#### `switch` 不带 `endswitch`
```twig
{% switch EXPRESSION %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: Syntax error, unexpected EOF in ..., there is a 'switch' block without 'endswitch'`:语法错误,意外的EOF在......中,有一个'switch'块没有'endswitch'。
#### `default` 不带 `switch`
```twig
{% default %}
```
不会抛出错误,因为`default`是过滤器的保留字像`{{ EXPRESSION | default(VALUE) }}`但在这种情况下,表达式只会输出一个空的字符''。
#### 嵌套 `switch`
```twig
{% switch EXPRESSION %}
{% switch EXPRESSION %}
{% endswitch %}
{% endswitch %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: A nested switch detected. There is no nested switch-case statements support in ... on line ...`:检测到嵌套switch。在行...不支持嵌套的switch-case语句...
#### `switch` 不带表达式
```twig
{% switch %}
{% case EXPRESSION %}
{% break %}
{% endswitch %}
```
将抛出致命错误:未捕获的`Fatal error: Uncaught Phalcon\Mvc\View\Exception: Syntax error, unexpected token %} in ... on line ...`:语法错误,意外的令牌%}在......在行...
### 循环上下文
一个特殊的变量可用于`for`循环内部,为您提供有关的信息
| 变量 | 描述 |
| ---------------- | ------------------------------------------------------------- |
| `loop.index` | 循环的当前迭代。(1索引) |
| `loop.index0` | 循环的当前迭代。(0索引) |
| `loop.revindex` | 循环结束时的迭代次数(1索引) |
| `loop.revindex0` | 循环结束时的迭代次数(0索引) |
| `loop.first` | 如果在第一次迭代中为true。 |
| `loop.last` | 如果在最后一次迭代中为true。 |
| `loop.length` | 要迭代的项目数 |
例子:
```twig
{% for robot in robots %}
{% if loop.first %}
Robots
-
{% for robot in robots %}
- {{ robot.name|e }} {% endfor %}
Robots
{% for robot in robots %} {% for part in robot.parts %} Robot: {{ robot.name|e }} Part: {{ part.name|e }}{% endfor %} {% endfor %} ``` 您可以使用以下语法获取PHP副本中的元素`keys`: ```twig {% set numbers = ['one': 1, 'two': 2, 'three': 3] %} {% for name, value in numbers %} Name: {{ name }} Value: {{ value }} {% endfor %} ``` 可以选择设置`if`判断: ```twig {% set numbers = ['one': 1, 'two': 2, 'three': 3] %} {% for value in numbers if value < 2 %} Value: {{ value }} {% endfor %} {% for name, value in numbers if name !== 'two' %} Name: {{ name }} Value: {{ value }} {% endfor %} ``` 如果在`for`中定义了`else`,则在迭代器中的表达式导致零迭代时将执行: ```twig
Robots
{% for robot in robots %} Robot: {{ robot.name|e }} Part: {{ part.name|e }}{% else %} There are no robots to show {% endfor %} ``` 替代语法: ```twig
Robots
{% for robot in robots %} Robot: {{ robot.name|e }} Part: {{ part.name|e }}{% elsefor %} There are no robots to show {% endfor %} ``` ### 循环控制 `break` 和 `continue` 语句可用于退出循环或强制当前块中的迭代: ```twig {# skip the even robots #} {% for index, robot in robots %} {% if index is even %} {% continue %} {% endif %} ... {% endfor %} ``` ```twig {# exit the foreach on the first even robot #} {% for index, robot in robots %} {% if index is even %} {% break %} {% endif %} ... {% endfor %} ``` ### If 作为PHP,`if`语句检查表达式是否被评估为true或false: ```twig
Cyborg Robots
-
{% for robot in robots %}
{% if robot.type === 'cyborg' %}
- {{ robot.name|e }} {% endif %} {% endfor %}
Robots
-
{% for robot in robots %}
{% if robot.type === 'cyborg' %}
- {{ robot.name|e }} {% else %}
- {{ robot.name|e }} (not a cyborg) {% endif %} {% endfor %}
# | Id | Name |
---|---|---|
{{ loop.index }} | {{ robot.id }} | {{ robot.name }} |
-
{%- for link in related_links %}
- {{ link.text }} {%- endfor %}
This is the content
{# Print related links again #}
{{ related_bar(links) }}
```
调用宏时,可以按名称传递参数:
```twig
{%- macro error_messages(message, field, type) %}
{{ type }}
{{ field }}
{%- endmacro %}
{# Call the macro #}
{{ error_messages('type': 'Invalid', 'message': 'The name is invalid', 'field': 'name') }}
```
宏可以返回值:
```twig
{%- macro my_input(name, class) %}
{% return text_field(name, 'class': class) %}
{%- endmacro %}
{# Call the macro #}
{{ '' ~ my_input('name', 'input-text') ~ '
' }} ``` 并接收可选参数: ```twig {%- macro my_input(name, class='input-text') %} {% return text_field(name, 'class': class) %} {%- endmacro %} {# Call the macro #} {{ '' ~ my_input('name') ~ '
' }} {{ '' ~ my_input('name', 'input-text') ~ '
' }} ``` ## 使用标签助手 Volt与`Phalcon\Tag`高度集成,因此可以很容易地使用Volt模板中该组件提供的帮助程序: ```twig {{ javascript_include('js/jquery.js') }} {{ form('products/save', 'method': 'post') }} {{ text_field('name', 'size': 32) }} {{ select('type', productTypes, 'using': ['id', 'name']) }} {{ submit_button('Send') }} {{ end_form() }} ``` 生成以下PHP: ```php 'post')); ?> 32)); ?> array('id', 'name'))); ?> {{ end_form() }} ``` 要调用`Phalcon\Tag`帮助程序,您只需要调用该方法的未完整版本: | 方法 | Volt 函数 | | --------------------------------- | -------------------- | | `Phalcon\Tag::checkField` | `check_field` | | `Phalcon\Tag::dateField` | `date_field` | | `Phalcon\Tag::emailField` | `email_field` | | `Phalcon\Tag::endForm` | `end_form` | | `Phalcon\Tag::fileField` | `file_field` | | `Phalcon\Tag::form` | `form` | | `Phalcon\Tag::friendlyTitle` | `friendly_title` | | `Phalcon\Tag::getTitle` | `get_title` | | `Phalcon\Tag::hiddenField` | `hidden_field` | | `Phalcon\Tag::image` | `image` | | `Phalcon\Tag::javascriptInclude` | `javascript_include` | | `Phalcon\Tag::linkTo` | `link_to` | | `Phalcon\Tag::numericField` | `numeric_field` | | `Phalcon\Tag::passwordField` | `password_field` | | `Phalcon\Tag::radioField` | `radio_field` | | `Phalcon\Tag::select` | `select` | | `Phalcon\Tag::selectStatic` | `select_static` | | `Phalcon\Tag::stylesheetLink` | `stylesheet_link` | | `Phalcon\Tag::submitButton` | `submit_button` | | `Phalcon\Tag::textArea` | `text_area` | | `Phalcon\Tag::textField` | `text_field` | ## 函数 Volt提供以下内置函数: | 名称 | 描述 | | ------------- | ----------------------------------------------------------- | | `content` | 包括在先前渲染阶段中生成的内容 | | `get_content` | 与 `content` 相同 | | `partial` | 动态加载当前模板中的局部视图 | | `super` | 渲染父块的内容 | | `time` | 使用相同的名称调用PHP函数 | | `date` | 使用相同的名称调用PHP函数 | | `dump` | 调用PHP函数 `var_dump()` | | `version` | 返回框架的当前版本 | | `constant` | 读取PHP常量 | | `url` | 使用“url”服务生成URL | ## 集成视图 此外,Volt与`Phalcon\Mvc\View`集成,您可以使用视图层次结构并包含部分: ```twig {{ content() }} ``` 部分包含在运行时,Volt还提供`include`,这将编译视图的内容并返回其内容作为视图的一部分,其中包括: ```twig {# Simple include of a partial #} {# Passing extra variables #} ``` ### Include `include`有一个特殊的行为,可以帮助我们在使用Volt时稍微提高性能,如果在包含文件时指定扩展名并且在编译模板时它存在,Volt可以内联包含它的父模板中的模板内容。如果`包含`传递的变量,则不会`内联模板`: ```twig {# The contents of 'partials/footer.volt' is compiled and inlined #} ``` ### Partial vs Include 选择使用`partial`或`include`时要记住以下几点: | 类型 | 描述 | | ---------- | ---------------------------------------------------------------------------------------------------------- | | `partial` |允许您包含在Volt和其他模板引擎中制作的模板 | | | 允许您传递类似变量的表达式,允许动态包含其他视图的内容 | | | 如果您必须包含的内容经常更改,则会更好 | | `includes` | 将已编译的内容复制到视图中,从而提高性能 | | | 仅允许包含使用Volt制作的模板 | | | 在编译时需要现有模板 | ## 模板继承 使用模板继承,您可以创建可由其他模板扩展的基本模板,从而允许重用代码。基本模板定义的`块`可以被子模板覆盖。让我们假设我们有以下基本模板: ```twig {# templates/base.volt #} {% block head %} {% endblock %}{% block content %}{% endblock %}
```
从其他模板我们可以扩展基础模板替换块:
```twig
{% extends 'templates/base.volt' %}
{% block title %}Index{% endblock %}
{% block head %}{% endblock %}
{% block content %}
Index
Welcome on my awesome homepage.
{% endblock %} ``` 并非所有块都必须在子模板中替换,只能替换所需的块。产生的最终结果如下: ```htmlIndex
Welcome on my awesome homepage.
Table of contents
{% endblock %} ``` 最后一个继承`layout.volt`的视图: ```twig {# index.volt #} {% extends 'layout.volt' %} {% block content %} {{ super() }}- Some option
- Some other option
Table of contents
- Some option
- Some other option
{{ post.title }}
{{ post.content }}
{% endcache %} ``` 缓存由`Phalcon\Cache`组件通过视图组件完成。在缓存视图片段部分中了解有关此集成的工作原理的更多信息。 ## 将服务注入模板 如果服务容器(DI)可用于Volt,则只需访问模板中的服务名称即可使用服务: ```twig {# Inject the 'flash' service #}{{ flash.output() }}
{# Inject the 'security' service #}
```
## 独立组件
在独立模式下使用Volt可以在下面演示:
```php
setOptions(
[
// ...
]
);
// Compile a template string returning PHP code
echo $compiler->compileString(
"{{ 'hello' }}"
);
// Compile a template in a file specifying the destination file
$compiler->compileFile(
'layouts/main.volt',
'cache/layouts/main.volt.php'
);
// Compile a template in a file based on the options passed to the compiler
$compiler->compile(
'layouts/main.volt'
);
// Require the compiled templated (optional)
require $compiler->getCompiledTemplatePath();
```
## 外部资源
* Sublime/Textmate的插件包可在[此处](https://github.com/phalcon/volt-sublime-textmate)获得
* [Album-O-Rama](https://album-o-rama.phalconphp.com)是一个使用Volt作为模板引擎的示例应用程序, [Github](https://github.com/phalcon/album-o-rama)
* [官方站点](https://phalconphp.com) 正在使用Volt作为模板引擎运行,[Github](https://github.com/phalcon/website)
* [Phosphorum](https://forum.phalconphp.com),Phalcon的论坛,也使用Volt,[Github](https://github.com/phalcon/forum)
* [Vökuró](https://vokuro.phalconphp.com),是另一个使用Volt的示例应用程序,[Github](https://github.com/phalcon/vokuro)