07 Шаблонизатор Volt
Volt: шаблонизатор
Volt-это сверхбыстрый и удобный для дизайнеров язык шаблонов, написанный на C для PHP. Он предоставляет вам набор помощников для написания представлений простым способом. Вольт сильно интегрирован с другими компонентами Phalcon, как раз по мере того как вы можете использовать его как отдельно стоящий компонент в ваших применениях.
Volt воодушевлён Jinja, первоначально созданным Armin Ronacher. Поэтому многие разработчики будут в знакомой территории, используя тот же синтаксис, который они использовали с аналогичными движками шаблонов. Синтаксис и функции Volt были улучшены с большим количеством элементов и, конечно же, с производительностью, к которой разработчики привыкли во время работы с Phalcon.
Введение
Представления Volt компилируются в чистый PHP-код, поэтому в основном они экономят усилия на написании PHP-кода вручную:
{# 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 в компоненте view, используя новое расширение или повторно используя стандарт .phtml
:
<?php use Phalcon\Mvc\View; use Phalcon\Mvc\View\Engine\Volt; // Регистрация Volt как сервиса $di->set( 'voltService', function ($view, $di) { $volt = new Volt($view, $di); $volt->setOptions( [ 'compiledPath' => '../app/compiled-templates/', 'compiledExtension' => '.compiled', ] ); return $volt; } ); // Регистрация Volt как шаблонизатора $di->set( 'view', function () { $view = new View(); $view->setViewsDir('../app/views/'); $view->registerEngines( [ '.volt' => 'voltService', ] ); return $view; } );
Используя стандартное расширение .phtml
:
<?php $view->registerEngines( [ '.phtml' => 'voltService', ] );
Вам не нужно указывать службу Volt в DI; вы также можете использовать двигатель Volt с настройками по умолчанию:
<?php $view->registerEngines( [ '.volt' => Phalcon\Mvc\View\Engine\Volt::class, ] );
Если вы не хотите повторно использовать Volt как службу, вы можете передать анонимную функцию для регистрации движка вместо имени службы:
<?php use Phalcon\Mvc\View; use Phalcon\Mvc\View\Engine\Volt; // Регистрировать Volt как механизм шаблонов с анонимной функцией $di->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 // Просто добавьте расширение .php к пути шаблона, // оставляя скомпилированные шаблоны в том же каталоге $volt->setOptions( [ 'compiledPath' => function ($templatePath) { return $templatePath . '.php'; } ] ); // Рекурсивно создать ту же структуру в другом каталоге $volt->setOptions( [ 'compiledPath' => function ($templatePath) { $dirName = dirname($templatePath); if (!is_dir('cache/' . $dirName)) { mkdir('cache/' . $dirName , 0777 , true); } return 'cache/' . $dirName . '/'. $templatePath . '.php'; } ] );
Основное использование
Представление состоит из вольт-кода, PHP и HTML. Для входа в режим Volt доступен набор специальных разделителей. {% ...%}
используется для выполнения таких операторов, как for-loops или assign values, и {{...}}
, выводит результат выражения в шаблон.
Ниже приведен минимальный шаблон, который иллюстрирует несколько основ:
{# app/views/posts/show.phtml #} <!DOCTYPE html> <html> <head> <title>{{ title }} - Пример блога</title> </head> <body> {% if show_navigation %} <ul id='navigation'> {% for item in menu %} <li> <a href='{{ item.href }}'> {{ item.caption }} </a> </li> {% endfor %} </ul> {% endif %} <h1>{{ post.title }}</h1> <div class='content'> {{ post.content }} </div> </body> </html>
Используя Phalcon\Mvc\View, вы можете передавать переменные из контроллера в представления. В приведенном выше примере в представление были переданы четыре переменные: show_navigation
, menu
, title
и post
:
<?php use Phalcon\Mvc\Controller; class PostsController extends Controller { public function showAction() { $post = Post::findFirst(); $menu = Menu::findFirst(); $this->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']
{{ post.title }} {# for $post->title #} {{ post['title'] }} {# for $post['title'] #}
Фильтры
Переменные можно форматировать или изменять с помощью фильтров. Pipe оператор |
используется для применения фильтров к переменным:
{{ post.title|e }} {{ post.content|striptags }} {{ name|capitalize|trim }}
Ниже приведен список доступных встроенных фильтров в Volt:
Фильтр | Описание |
---|---|
abs |
Применяет функцию PHP abs к значению. |
capitalize |
Заглавная строка, применяя функцию PHP ucwords к значению |
convert_encoding |
Преобразует строку из одной кодировки в другую |
default |
Устанавливает значение по умолчанию в том случае, если вычисленное выражение пусто (не задано или не оценивается как ложное значение) |
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. |
json_encode |
Преобразует значение в его представление JSON |
json_decode |
Преобразует значение из представления JSON в представление PHP |
join |
Присоединяется к частям массива с помощью разделителя join |
keys |
Возвращает ключи массива с помощью array_keys |
left_trim |
Применяет PHP-функцию ltrim к значению. Удаление лишних пробелов |
length |
Подсчитывает длину строки или количество элементов в массиве или объекте |
lower |
Изменяет регистр строки на нижний регистр |
nl2br |
Изменения строки \n на строки (<br /> ). Использует PHP функцию nl2br |
right_trim |
Применяет PHP-функцию rtrim к значению. Удаление лишних пробелов |
sort |
Сортировка массива с помощью функции PHP asort |
stripslashes |
Применяет к значению PHP-функцию stripslashes. Удаление экранированных кавычек |
striptags |
Применяет функцию PHP striptags к значению. Удаление HTML-тегов |
trim |
Применяет PHP-функцию trim к значению. Удаление лишних пробелов |
upper |
Изменяет регистр строки на верхний регистр |
url_encode |
Применяет PHP-функцию urlencode к значению |
Примеры:
{# e or escape filter #} {{ '<h1>Hello<h1>'|e }} {{ '<h1>Hello<h1>'|escape }} {# trim filter #} {{ ' hello '|trim }} {# striptags filter #} {{ '<h1>Hello<h1>'|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') }}
Комментарии
Комментарии также могут быть добавлены в шаблон с использованием разделителей {# ... #}
. Весь текст внутри них просто игнорируется в выходном потоке:
{# примечание: это комментарий {% set price = 100; %} #}
Список структур управления
Volt предоставляет набор базовых, но мощных структур управления для использования в шаблонах:
For
Цикл над каждым элементом в последовательности. В следующем примере показано, как пройти набор 'robots' и напечатать его / ее имя:
<h1>Robots</h1> <ul> {% for robot in robots %} <li> {{ robot.name|e }} </li> {% endfor %} </ul>
циклы for могут быть вложенными:
<h1>Robots</h1> {% for robot in robots %} {% for part in robot.parts %} Robot: {{ robot.name|e }} Part: {{ part.name|e }} <br /> {% endfor %} {% endfor %}
Вы можете получить ключи keys
элементов, как в PHP-аналоге, используя следующий синтаксис:
{% set numbers = ['one': 1, 'two': 2, 'three': 3] %} {% for name, value in numbers %} Name: {{ name }} Value: {{ value }} {% endfor %}
Оценку if
можно выборочно установить:
{% 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 %}
Если else
определен внутри for
, он будет выполнен, если выражение в итераторе приведет к нулевым итерациям:
<h1>Robots</h1> {% for robot in robots %} Robot: {{ robot.name|e }} Part: {{ part.name|e }} <br /> {% else %} Нет роботов, чтобы показать {% endfor %}
Альтернативный синтаксис:
<h1>Robots</h1> {% for robot in robots %} Robot: {{ robot.name|e }} Part: {{ part.name|e }} <br /> {% elsefor %} Нет роботов, чтобы показать {% endfor %}
Элементы управления цикла
Операторы break
и continue
могут использоваться для выхода из цикла или принудительной итерации в текущем блоке:
{# skip the even robots #} {% for index, robot in robots %} {% if index is even %} {% continue %} {% endif %} ... {% endfor %}
{# 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:
<h1>Роботы-киборги</h1> <ul> {% for robot in robots %} {% if robot.type === 'cyborg' %} <li>{{ robot.name|e }}</li> {% endif %} {% endfor %} </ul>
Также поддерживается оператор else
:
<h1>Robots</h1> <ul> {% for robot in robots %} {% if robot.type === 'cyborg' %} <li>{{ robot.name|e }}</li> {% else %} <li>{{ robot.name|e }} (not a cyborg)</li> {% endif %} {% endfor %} </ul>
Оператор
elseif
может использоваться вместе с if
для эмуляции блока switch
:
{% 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
, позволяющий создавать логические пути выполнения в приложении:
{% 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
приведет к синтаксической ошибке. Поэтому пустые строки и пробелы могут быть удалены, чтобы уменьшить количество ошибок см. здесь.
case
без switch
{% case EXPRESSION %}
Будет бросать Fatal error: Uncaught Phalcon\Mvc\View\Exception: Unexpected CASE
.
switch
без endswitch
{% switch EXPRESSION %} Will throw `Fatal error: Uncaught Phalcon\Mvc\View\Exception: Syntax error, unexpected EOF in ..., there is a 'switch' block without 'endswitch'`.
default
без switch
{% default %}
Не выдаст ошибку, так как default
является зарезервированным словом для таких фильтров, как {{ EXPRESSION | default(VALUE) }}
, но в этом случае выражение выдаст только пустой символ '' .
вложенный switch
{% 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 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 |
Количество элементов перебора |
Example:
{% for robot in robots %} {% if loop.first %} <table> <tr> <th>#</th> <th>Id</th> <th>Name</th> </tr> {% endif %} <tr> <td>{{ loop.index }}</td> <td>{{ robot.id }}</td> <td>{{ robot.name }}</td> </tr> {% if loop.last %} </table> {% endif %} {% endfor %}
Присвоения
Переменные могут быть изменены в шаблоне с помощью инструкции 'set':
{% set fruits = ['Apple', 'Banana', 'Orange'] %} {% set name = robot.name %}
В одной инструкции допускается несколько присвоений:
{% set fruits = ['Apple', 'Banana', 'Orange'], name = robot.name, active = true %}
Кроме того, можно использовать составные операторы присваивания:
{% set price += 100.00 %} {% set age *= 5 %}
Доступны следующие операторы:
Оператор | Описание |
---|---|
= |
Стандартное присвоение |
+= |
Сложение с присвоением |
-= |
Вычитание с присвоением |
\*= |
Умножение с присвоением |
/= |
Деление с присвоением |
Выражения
Volt обеспечивает базовый набор поддержки выражений, включая литералы и общие операторы. Выражение может быть оценено и напечатано с помощью разделителей {{
и }}
:
{{ (1 + 1) * 2 }}
Если выражение нужно оценивать без печати, можно использовать оператор do
:
{% do (1 + 1) * 2 %}
Литералы
Поддерживаются следующие литералы:
Фильтр | Описание |
---|---|
'this is a string' |
Текст между двойными кавычками или одинарными кавычками обрабатывается как строки |
100.25 |
Числа с десятичной запятой обрабатываются как double / floats |
100 |
Числа без десятичной части обрабатываются как целые числа |
false |
Константа 'false' - логическое значение false |
true |
Константа 'true' - логическое значение true |
null |
Константа 'null' - значение Null |
Массивы
Если вы используете PHP 5.3 или >= 5.4 можно создавать массивы, заключив список значений в квадратных скобках:
{# 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'] }}
Фигурные скобки также могут использоваться для определения массивов или хэшей:
{% set myArray = {'Apple', 'Banana', 'Orange'} %}
{% set myHash = {'first': 1, 'second': 4/2, 'third': '3'} %}
Математика
Вычисления в шаблонах можно выполнять с помощью следующих операторов:
Operator | Description |
---|---|
+ |
Выполнение операции сложения. {{ 2 + 3 }} возвращает 5 |
- |
Выполнение операции вычитания {{ 2 - 3 }} возвращает -1 |
* |
Выполнение операции умножения {{ 2 * 3 }} возвращает 6 |
/ |
Выполнение операции деления {{ 10 / 2 }} возвращает 5 |
% |
Вычислить остаток от деления целого числа {{ 10 % 3 }} возвращает 1 |
Сравнения
Доступны следующие операторы сравнения:
Оператор | Описание |
---|---|
== |
Проверяет, равны ли оба операнда |
!= |
Проверяет, не равны ли оба операнда |
<> |
Проверяет, не равны ли оба операнда |
> |
Проверяет, больше ли левый операнд, чем правый |
< |
Проверяет, является ли левый операнд меньше правого |
<= |
Проверяет, является ли левый операнд меньше или равен правому операнду |
>= |
Проверяет, является ли левый операнд больше или равен правому операнду |
=== |
Проверяет, идентичны ли оба операнда |
!== |
Проверяет, не идентичны ли оба операнда |
Логика
Логические операторы полезны при вычислении выражения if
для объединения нескольких тестов:
Operator | Description |
---|---|
or |
Возвращает true, если левый или правый операнд оценивается как истина |
and |
Возвращает true, если левый и правый операнды оцениваются как true |
not |
Отрицает выражение |
( expr ) |
Выражения групп скобок |
Остальные операторы
Дополнительные операторы доступны следующие операторы:
Оператор | Описание |
---|---|
~ |
Объединяет оба операнда {{ 'hello ' ~ 'world' }} |
| |
Применяет фильтр в правом операнде к левому {{ 'hello'|uppercase }} |
.. |
Создает диапазон {{ 'a'..'z' }} {{ 1..10 }} |
is |
То же, что == (равно), также выполняет тесты |
in |
Чтобы проверить, содержится ли выражение в других выражениях if 'a' in 'abc' |
is not |
То же самое != (не равный) |
'a' ? 'b' : 'c' |
Тернарный оператор. То же, что и тернарный оператор PHP |
++ |
Увеличивает значение на 1 |
-- |
Уменьшение значения на 1 |
В следующем примере показано, как использовать операторы:
{% set robots = ['Voltron', 'Astro Boy', 'Terminator', 'C3PO'] %} {% for index in 0..robots|length %} {% if robots[index] is defined %} {{ 'Name: ' ~ robots[index] }} {% endif %} {% endfor %}
Тесты
Тесты можно использовать для проверки, имеет ли переменная допустимое ожидаемое значение. Оператор is
используется для проведения испытаний:
{% set robots = ['1': 'Voltron', '2': 'Astro Boy', '3': 'Terminator', '4': 'C3PO'] %}
{% for position, name in robots %}
{% if position is odd %}
{{ name }}
{% endif %}
{% endfor %}
Следующие встроенные тесты доступны в Volt:
Test | Description |
---|---|
defined |
Проверяет, определена ли переменная (isset() ) |
divisibleby |
Проверяет, делится ли значение на другое |
empty |
Проверяет, является ли переменная пустой |
even |
Проверяет, является ли числовое значение четным |
iterable |
Проверяет, является ли значение итерационным. Можно пройти с помощью оператора for |
numeric |
Проверяет, является ли значение числовым |
odd |
Проверяет, является ли числовое значение нечетным |
sameas |
Проверяет, совпадает ли значение с другим значением |
scalar |
Проверяет, является ли значение скалярным (не массивом или объектом) |
type |
Проверяет, имеет ли значение указанный тип |
Еще много примеров:
{% 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, могут принимать параметры и возвращать значения:
{# Macro 'отображение списка ссылок на связанные темы' #} {%- macro related_bar(related_links) %} <ul> {%- for link in related_links %} <li> <a href='{{ url(link.url) }}' title='{{ link.title|striptags }}'> {{ link.text }} </a> </li> {%- endfor %} </ul> {%- endmacro %} {# Печать связанных ссылок #} {{ related_bar(links) }} <div>Это содержание</div> {# Print related links again #} {{ related_bar(links) }}
При вызове макросов параметры могут передаваться по имени:
{%- macro error_messages(message, field, type) %} <div> <span class='error-type'>{{ type }}</span> <span class='error-field'>{{ field }}</span> <span class='error-message'>{{ message }}</span> </div> {%- endmacro %} {# Вызов макроса #} {{ error_messages('type': 'Invalid', 'message': 'The name is invalid', 'field': 'name') }}
Макросы могут возвращать значения:
{%- macro my_input(name, class) %} {% return text_field(name, 'class': class) %} {%- endmacro %} {# Вызов макроса #} {{ '<p>' ~ my_input('name', 'input-text') ~ '</p>' }}
И получить дополнительные параметры:
{%- macro my_input(name, class='input-text') %} {% return text_field(name, 'class': class) %} {%- endmacro %} {# Вызов макроса #} {{ '<p>' ~ my_input('name') ~ '</p>' }} {{ '<p>' ~ my_input('name', 'input-text') ~ '</p>' }}
Использование помощников по тегам
Volt сильно интегрирован с Phalcon\Tag, поэтому легко использовать хелперы обеспеченные этим компонентом в шаблоне Volt:
{{ javascript_include('js/jquery.js') }} {{ form('products/save', 'method': 'post') }} <label for='name'>Name</label> {{ text_field('name', 'size': 32) }} <label for='type'>Type</label> {{ select('type', productTypes, 'using': ['id', 'name']) }} {{ submit_button('Send') }} {{ end_form() }}
Генерируется следующий PHP:
<?php echo Phalcon\Tag::javascriptInclude('js/jquery.js') ?> <?php echo Phalcon\Tag::form(array('products/save', 'method' => 'post')); ?> <label for='name'>Name</label> <?php echo Phalcon\Tag::textField(array('name', 'size' => 32)); ?> <label for='type'>Type</label> <?php echo Phalcon\Tag::select(array('type', $productTypes, 'using' => array('id', 'name'))); ?> <?php echo Phalcon\Tag::submitButton('Send'); ?> {{ 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, вы можете играть с иерархией представлений и включать также частичные:
{{ content() }} <!-- Простое включение частичного представления--> <div id='footer'>{{ partial('partials/footer') }}</div> <!-- Передача дополнительных переменных --> <div id='footer'>{{ partial('partials/footer', ['links': links]) }}</div>
Часть включается во время выполнения, Volt также предоставляет include
, это компилирует содержимое представления и возвращает его содержимое как часть представления, которое было включено:
{# Простое включение части #} <div id='footer'> {% include 'partials/footer' %} </div> {# Передача дополнительных переменных #} <div id='footer'> {% include 'partials/footer' with ['links': links] %} </div>
Include
У include
есть специальное поведение, которое поможет нам немного улучшить производительность при использовании Volt, если вы укажете расширение при включении файла, и оно существует, когда шаблон компилируется, Volt может встроить содержимое шаблона в родительский шаблон, где он включен. Шаблоны не являются встроенными, если include
имеют переменные, переданные с with
:
{# Содержимое 'partials/footer.volt' скомпилировано и встроено #} <div id='footer'> {% include 'partials/footer.volt' %} </div>
Partial против Include
При использовании функции partial
или include
помните о следующих моментах:
Тип | Описание |
---|---|
partial |
позволяет включать шаблоны, выполненные в Volt и других шаблонизаторах |
позволяет передать выражение в виде переменной, позволяющей динамически включать содержимое другого представления | |
лучше, если содержание, которое вы должны включать изменяется часто | |
includes |
копирует скомпилированное содержимое в представление, что повышает производительность |
только позволяет включать шаблоны, сделанные с помощью Volt | |
требует наличия шаблона во время компиляции |
Наследование Шаблонов
С помощью наследования шаблонов вы можете создавать базовые шаблоны, которые могут быть расширены другими шаблонами, позволяющими повторно использовать код. Базовый шаблон определяет блоки, которые могут быть переопределены дочерним шаблоном. Давайте представим, что у нас есть следующий базовый шаблон:
{# templates/base.volt #} <!DOCTYPE html> <html> <head> {% block head %} <link rel='stylesheet' href='style.css' /> {% endblock %} <title>{% block title %}{% endblock %} - My Webpage</title> </head> <body> <div id='content'>{% block content %}{% endblock %}</div> <div id='footer'> {% block footer %}© Copyright 2015, All rights reserved.{% endblock %} </div> </body> </html>
Из другого шаблона мы можем расширить базовый шаблон, заменив блоки:
{% extends 'templates/base.volt' %} {% block title %}Index{% endblock %} {% block head %}<style type='text/css'>.important { color: #336699; }</style>{% endblock %} {% block content %} <h1>Index</h1> <p class='important'>Welcome on my awesome homepage.</p> {% endblock %}
Не все блоки должны быть заменены в дочернем шаблоне, только те, которые необходимы. Окончательный результат будет следующим:
<!DOCTYPE html> <html> <head> <style type='text/css'>.important { color: #336699; }</style> <title>Index - My Webpage</title> </head> <body> <div id='content'> <h1>Index</h1> <p class='important'>Welcome on my awesome homepage.</p> </div> <div id='footer'> © Copyright 2015, All rights reserved. </div> </body> </html>
Множественное наследование
Расширенные шаблоны могут расширять другие шаблоны. Это показано в следующем примере:
{# main.volt #} <!DOCTYPE html> <html> <head> <title>Title</title> </head> <body> {% block content %}{% endblock %} </body> </html>
Шаблон layout.volt
расширяет main.volt
{# layout.volt #} {% extends 'main.volt' %} {% block content %} <h1>Table of contents</h1> {% endblock %}
Наконец, представление, которое расширяется layout.volt
:
{# index.volt #} {% extends 'layout.volt' %} {% block content %} {{ super() }} <ul> <li>Some option</li> <li>Some other option</li> </ul> {% endblock %}
Визуализация index.volt
дает:
<!DOCTYPE html> <html> <head> <title>Title</title> </head> <body> <h1>Table of contents</h1> <ul> <li>Some option</li> <li>Some other option</li> </ul> </body> </html>
Обратите внимание на вызов функции super()
. С помощью этой функции можно отобразить содержимое родительского блока. Как partials, путь, установленный в extends
, является относительным путем в текущем каталоге представлений (т. е. app/views/
).
Режим Autoescape
Вы можете включить авто-экранирование всех переменных, выведенных в блок, используя режим autoescape :
Manually escaped: {{ robot.name|e }} {% autoescape true %} Autoescaped: {{ robot.name }} {% autoescape false %} No Autoescaped: {{ robot.name }} {% endautoescape %} {% endautoescape %}
Расширение Volt
В отличие от других шаблонизаторов, Volt не требуется для запуска скомпилированных шаблонов. После того, как шаблоны скомпилированы нет никакой зависимости от Volt. Имея в виду независимость от производительности, Volt действует только как компилятор для шаблонов PHP.
Компилятор Volt позволяет расширить его, добавив больше функций, тестов или фильтров к существующим.
Функции
Функции действуют как обычные функции PHP, в качестве имени функции требуется допустимое имя строки. Функции можно добавлять с помощью двух стратегий, возвращая простую строку или используя анонимную функцию. Всегда требуется, чтобы выбранная стратегия возвращала допустимое строковое выражение PHP:
<?php use Phalcon\Mvc\View\Engine\Volt; $volt = new Volt($view, $di); $compiler = $volt->getCompiler(); // Это связывает имя функции 'shuffle' в Volt с функцией PHP 'str_shuffle' $compiler->addFunction('shuffle', 'str_shuffle');
Зарегистрируйте функцию с помощью анонимной функции. В этом случае мы используем $resolvedArgs
для передачи аргументов точно так, как они были переданы в аргументах функции:
<?php $compiler->addFunction( 'widget', function ($resolvedArgs, $exprArgs) { return 'MyLibrary\Widgets::get(' . $resolvedArgs . ')'; } );
Обрабатывать аргументы независимо и неразрешено:
<?php $compiler->addFunction( 'repeat', function ($resolvedArgs, $exprArgs) use ($compiler) { // Разрешить первый аргумент $firstArgument = $compiler->expression($exprArgs[0]['expr']); // Проверяет, прошел ли второй аргумент if (isset($exprArgs[1])) { $secondArgument = $compiler->expression($exprArgs[1]['expr']); } else { // Используйте «10» по умолчанию $secondArgument = '10'; } return 'str_repeat(' . $firstArgument . ', ' . $secondArgument . ')'; } );
Создание кода на основе доступности некоторых функций:
<?php $compiler->addFunction( 'contains_text', function ($resolvedArgs, $exprArgs) { if (function_exists('mb_stripos')) { return 'mb_stripos(' . $resolvedArgs . ')'; } else { return 'stripos(' . $resolvedArgs . ')'; } } );
Встроенные функции можно переопределить, добавив функцию с именем:
<?php // Заменить встроенную функцию dump $compiler->addFunction('dump', 'print_r');
Фильтры
Фильтр имеет следующую форму в шаблоне: leftExpr|name(optional-args)
. Добавление новых фильтров аналогично описанию функций:
<?php // Это создает фильтр 'hash', который использует функцию PHP 'md5' $compiler->addFilter('hash', 'md5');
<?php $compiler->addFilter( 'int', function ($resolvedArgs, $exprArgs) { return 'intval(' . $resolvedArgs . ')'; } );
Встроенные фильтры можно переопределить, добавив функцию с ее именем:
<?php // Заменить встроенный фильтр 'capitalize' $compiler->addFilter('capitalize', 'lcfirst');
Расширения
С помощью расширений разработчик имеет больше возможностей для расширения механизма шаблонов и переопределения компиляции конкретной инструкции, изменения поведения выражения или оператора, добавления функций/фильтров и т. д.
Расширение — это класс, реализующий события, инициированные Volt как метод самого себя. Например, класс, приведенный ниже, позволяет использовать любую функцию PHP в Volt:
<?php class PhpFunctionExtension { /** * Этот метод вызывается при любой попытке компиляции вызова функции */ public function compileFunction($name, $arguments) { if (function_exists($name)) { return $name . '('. $arguments . ')'; } } }
Приведенный выше класс реализует метод compileFunction
, который вызывается перед любой попыткой компиляции вызова функции в любом шаблоне. Цель расширения-проверить, является ли компилируемая функция PHP-функцией, позволяющей вызывать ее из шаблона. События в расширениях должны возвращать корректный PHP код, который будет использоваться в результате компиляции, а не сгенерированный Volt. Если событие не возвращает строку компиляции осуществляется с помощью поведения по умолчанию движка.
В расширениях доступны следующие события компиляции:
Событие/Метод | Описание |
---|---|
compileFunction |
Срабатывает перед компиляцией любого вызова функции в шаблоне |
compileFilter |
Срабатывает перед компиляцией любого вызова фильтра в шаблоне |
resolveExpression |
Срабатывает перед компиляцией любого выражения. Это позволяет разработчику переопределять операторы |
compileStatement |
Срабатывает перед компиляцией любого выражения. Это позволяет разработчику переопределить любой оператор |
Расширения Volt должны быть зарегистрированы в компиляторе, что делает их доступными во время компиляции:
<?php // Зарегистрировать расширение в компиляторе $compiler->addExtension( new PhpFunctionExtension() );
Кэширование фрагментов представления
С Volt легко кэшировать фрагменты. Это кэширование повышает производительность, предотвращая выполнение PHP содержимого блока при каждом отображении представления:
{% cache 'sidebar' %} <!-- генерировать этот контент медленно, поэтому мы будем кэшировать его --> {% endcache %}
Установка определенного количества секунд:
{# кэш боковой панели на 1 час #} {% cache 'sidebar' 3600 %} <!-- генерировать этот контент медленно, поэтому мы будем кэшировать его --> {% endcache %}
В качестве ключа кэша можно использовать любое допустимое выражение:
{% cache ('article-' ~ post.id) 3600 %} <h1>{{ post.title }}</h1> <p>{{ post.content }}</p> {% endcache %}
Кэширование осуществляется компонентом Phalcon\Cache
через компонент view. Подробнее об этой интеграции см. В разделе кэширование фрагментов представления.
Внедрение служб в шаблон
Если контейнер служб (DI) доступен для Volt, можно использовать службы, получив доступ только к имени службы в шаблоне:
{# Впрыснуть службу 'flash' #} <div id='messages'>{{ flash.output() }}</div> {# Впрыснуть службу 'security' #} <input type='hidden' name='token' value='{{ security.getToken() }}'>
Автономный компонент
Использование Volt в автономном режиме можно продемонстрировать ниже:
<?php use Phalcon\Mvc\View\Engine\Volt\Compiler as VoltCompiler; // Создать компилятор $compiler = new VoltCompiler(); // При необходимости добавьте некоторые параметры $compiler->setOptions( [ // ... ] ); // Скомпилировать строку шаблона, возвращающую PHP-код echo $compiler->compileString( "{{ 'hello' }}" ); // Скомпилировать шаблон в файле с указанием целевого файла $compiler->compileFile( 'layouts/main.volt', 'cache/layouts/main.volt.php' ); // Компилировать шаблон в файле на основе параметров, переданных компилятору $compiler->compile( 'layouts/main.volt' ); // Требовать скомпилированные шаблонные (необязательные) require $compiler->getCompiledTemplatePath();
Внешние ресурсы
- Здесь доступен комплект для Sublime/Textmate
- Album-O-Rama - пример приложения, использующего Volt в качестве механизма шаблонов, Github
- Наш веб-сайт работает с использованием Volt в качестве механизма шаблонов Github
- Phosphorum, форум Phalcon, также использует Volt, Github
- Vökuró, является еще одним примером приложения, которое использует Volt, Github