Twig для разработчиков шаблонов
Этот документ описывает синтаксис и семантику движка шаблонов и будет наиболее полезен в качестве справочника для тех, кто создаёт шаблоны Twig.
Обзор
Шаблон — это обычный текстовый файл. Он может генерировать любой текстовый формат (HTML, XML, CSV, LaTeX и т.д.). У него нет специфического расширения, .html или .xml подойдут.
Шаблон содержит переменные или выражения, которые заменяются значениями при оценке шаблона, и теги, которые управляют логикой шаблона.
Ниже приведён минимальный шаблон, иллюстрирующий некоторые основы. Более подробные сведения будут рассмотрены позднее:
<!DOCTYPE html>
<html>
<head>
<title>My Webpage</title>
</head>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
<h1>My Webpage</h1>
{{ a_variable }}
</body>
</html>
Существует два вида разделителей: {% ... %} и {{ ... }}. Первый используется для выполнения операторов, таких как циклы for, второй — для вывода результата выражения.
Интеграция с IDE
Многие IDE поддерживают подсветку синтаксиса и автодополнение для Twig:
- Textmate через пакет Twig bundle
- Vim через плагин синтаксиса Jinja или плагин vim-twig
- Netbeans через плагин Twig (до версии 7.1, встроенный начиная с 7.2)
- PhpStorm (встроенный начиная с версии 2.1)
- Eclipse через плагин Twig
- Sublime Text через пакет Twig bundle
- GtkSourceView через определение языка Twig Twig (используется в gedit и других проектах)
- Coda и SubEthaEdit через режим синтаксиса Twig Twig
- Coda 2 через другой режим синтаксиса Twig Twig
- Komodo и Komodo Edit через режим подсветки/проверки синтаксиса Twig
- Notepad++ через Notepad++ Twig Highlighter
- Emacs через web-mode.el
- Atom через PHP-twig for atom
- Visual Studio Code через пакет Twig pack
Также, TwigFiddle — это онлайн-сервис, позволяющий выполнять шаблоны Twig из браузера; он поддерживает все версии Twig.
Переменные
Приложение передаёт переменные в шаблоны для обработки в шаблоне. Переменные также могут иметь атрибуты или элементы, к которым можно получить доступ. Визуальное представление переменной сильно зависит от приложения, которое её предоставляет.
Используйте точку (.) для доступа к атрибутам переменной (методы или свойства объекта PHP, или элементы массива PHP):
{{ foo.bar }}
Примечание
Важно знать, что фигурные скобки не являются частью переменной, а частью оператора вывода. При доступе к переменным внутри тегов фигурные скобки не ставьте.
Если переменная или атрибут не существует, вы получите значение null при включенном варианте false; в противном случае, если strict_variables включён, Twig выведет ошибку (см. параметры окружения).
Примечание
Если нужно получить доступ к динамическому атрибуту переменной, используйте функцию attribute вместо этого.
Функция attribute также полезна, когда атрибут содержит специальные символы (например, -, который интерпретируется как оператор минус):
{# equivalent to the non-working foo.data-foo #}
{{ attribute(foo, 'data-foo') }}
Глобальные переменные
Следующие переменные всегда доступны в шаблонах:
-
_self: ссылается на текущее имя шаблона; -
_context: ссылается на текущий контекст; -
_charset: ссылается на текущую кодировку.
Установка переменных
Можно присваивать значения переменным внутри блоков кода. Присвоение выполняется с помощью тега set:
{% set foo = 'foo' %}
{% set foo = [1, 2] %}
{% set foo = {'foo': 'bar'} %}
Фильтры
Переменные могут быть изменены с помощью фильтров. Фильтры отделяются от переменной символом «|» (|). Можно использовать несколько фильтров последовательно. Результат одного фильтра передаётся на вход следующему.
В следующем примере удаляются все HTML-теги из name и выполняется приведение к верхнему регистру:
{{ name|striptags|title }}
Фильтры, принимающие аргументы, имеют круглые скобки вокруг аргументов. В этом примере элементы списка соединяются запятыми:
{{ list|join(', ') }}
Чтобы применить фильтр к части кода, оберните её тегом apply:
{% apply upper %}
This text becomes uppercase
{% endapply %}
Дополнительные сведения о встроенных фильтрах см. на странице фильтров.
Примечание
Тег apply был добавлен в Twig 2.9; используйте тег filter для предыдущих версий.
Функции
Для генерации содержимого можно вызывать функции. Функции вызываются по их имени, за которым следуют круглые скобки (()), и могут иметь аргументы.
Например, функция range возвращает список, содержащий арифметическую прогрессию целых чисел:
{% for i in range(0, 3) %}
{{ i }},
{% endfor %}
Дополнительные сведения о встроенных функциях см. на странице функций.
Именованные аргументы
{% for i in range(low=1, high=10, step=2) %}
{{ i }},
{% endfor %}
Использование именованных аргументов делает шаблоны более явными в отношении смысла передаваемых аргументов:
{{ data|convert_encoding('UTF-8', 'iso-2022-jp') }}
{# versus #}
{{ data|convert_encoding(from='iso-2022-jp', to='UTF-8') }}
Именованные аргументы также позволяют пропустить некоторые аргументы, для которых вы не хотите изменять значение по умолчанию:
{# 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") }}
Можно также использовать позиционные и именованные аргументы в одном вызове, при этом позиционные аргументы должны всегда предшествовать именованным:
{{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }}
Подсказка
На каждой странице документации функций и фильтров есть раздел, где перечислены все поддерживаемые имена аргументов.
Структура управления
Структура управления относится ко всем элементам, которые контролируют поток программы — условные операторы (т.е. if/elseif/else), циклы for, а также блоки. Структуры управления появляются внутри блоков {% ... %}.
Например, чтобы отобразить список пользователей, предоставленных в переменной под названием users, используйте тег for:
<h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
Тег if можно использовать для проверки выражения:
{% if users|length > 0 %}
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}
Дополнительные сведения о встроенных тегах см. на странице тегов.
Комментарии
Чтобы прокомментировать часть строки в шаблоне, используйте синтаксис комментариев {# ...
#}. Это полезно для отладки или добавления информации для других разработчиков шаблонов или для себя:
{# note: disabled template because we no longer use this
{% for user in users %}
...
{% endfor %}
#}
Включение других шаблонов
Функция include полезна для включения шаблона и возврата отрендеренного содержимого этого шаблона в текущий:
{{ include('sidebar.html') }}
По умолчанию включённые шаблоны имеют доступ к тому же контексту, что и шаблон, который их включает. Это означает, что любая переменная, определённая в основном шаблоне, также будет доступна во включённом шаблоне:
{% for box in boxes %}
{{ include('render_box.html') }}
{% endfor %}
Включённый шаблон render_box.html может получить доступ к переменной box.
Имя шаблона зависит от загрузчика шаблонов. Например, \Twig\Loader\FilesystemLoader позволяет получить доступ к другим шаблонам, задавая имя файла. Вы можете получить доступ к шаблонам в подкаталогах, используя слеш:
{{ include('sections/articles/sidebar.html') }}
Это поведение зависит от приложения, использующего Twig.
Наследование шаблонов
Наиболее мощной частью Twig является наследование шаблонов. Наследование шаблонов позволяет создать базовый шаблон-«каркас», содержащий все общие элементы вашего сайта и определяющий блоки, которые дочерние шаблоны могут переопределить.
Концепцию легче понять, начав с примера.
Определим базовый шаблон, base.html, который определяет HTML-шаблон документа, который может использоваться для страницы с двумя колонками:
<!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, — это сообщает движку шаблонов, что дочерний шаблон может переопределить эти части шаблона.
Дочерний шаблон может выглядеть так:
{% 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. Это возвращает результаты родительского блока:
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ parent() }}
{% endblock %}
Подсказка
Страница документации для тега extends описывает более продвинутые функции, такие как вложенность блоков, область видимости, динамическое наследование и условное наследование.
Примечание
Twig также поддерживает множественное наследование через «горизонтальное повторное использование» с помощью тега use.
Обработка HTML-экранирования
При генерации HTML из шаблонов всегда есть риск, что переменная будет содержать символы, влияющие на результирующий HTML. Есть два подхода: ручное экранирование каждой переменной или автоматическое экранирование всего по умолчанию.
Twig поддерживает оба подхода, автоматическое экранирование включено по умолчанию.
Стратегия автоматического экранирования может быть настроена через опцию autoescape и по умолчанию равна html.
Работа с ручным экранированием
Если ручное экранирование включено, вам необходимо экранировать переменные при необходимости. Что экранировать? Любую переменную, которая поступает из ненадежного источника.
Экранирование выполняется с помощью фильтра escape или e:
{{ user.username|e }}
По умолчанию фильтр escape использует стратегию html, но в зависимости от контекста экранирования, вы можете явно использовать другую стратегию:
{{ user.username|e('js') }}
{{ user.username|e('css') }}
{{ user.username|e('url') }}
{{ user.username|e('html_attr') }}
Работа с автоматическим экранированием
Независимо от того, включено ли автоматическое экранирование или нет, вы можете пометить часть шаблона для экранирования или не экранирования с помощью тега autoescape:
{% autoescape %}
Everything will be automatically escaped in this block (using the HTML strategy)
{% endautoescape %}
По умолчанию автоматическое экранирование использует стратегию экранирования html. Если вы выводите переменные в других контекстах, вам нужно явно экранировать их с помощью соответствующей стратегии экранирования:
{% autoescape 'js' %}
Everything will be automatically escaped in this block (using the JS strategy)
{% endautoescape %}
Экранирование
Иногда желательно или даже необходимо, чтобы Twig игнорировал части, которые он в противном случае обрабатывал как переменные или блоки. Например, если используется стандартный синтаксис, и вы хотите использовать {{ как строку без обработки в шаблоне, а не начинать переменную, вам нужно использовать трюк.
Самый простой способ — вывести разделитель переменных ({{) с помощью выражения переменной:
{{ '{{' }}
Для больших разделов имеет смысл пометить блок verbatim.
Макросы
Макросы сопоставимы с функциями в обычных языках программирования. Они полезны для повторного использования фрагментов HTML, чтобы не повторять себя. Они описаны в документации к тегу macro.
Выражения
Twig допускает выражения повсюду.
Примечание
Порядок приоритета операторов следующий, с операторами с наименьшим приоритетом в начале: ?: (тернарный оператор), b-and, b-xor, b-or, or, and, ==, !=, <=>, <, >, >=, <=, in, matches, starts with, ends with, .., +, -, ~, *, /, //, %, is (тесты), **, ??, | (фильтры), [], и .:
{% 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"}: Словари определяются списком ключей и значений, разделённых запятыми (,) и заключёнными в фигурные скобки ({}):{# 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.
Массивы и словари могут быть вложены:
{% set foo = [1, {"foo": "bar"}] %}
Подсказка
Использование строк в двойных или одинарных кавычках не влияет на производительность, но интерполяция строк поддерживается только в строках в двойных кавычках.
Математические операции
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, если левое и правое операнды оба истинны. -
or: Возвращает true, если левое или правое операнд истинно. -
not: Отрицает утверждение. -
(expr): Группирует выражение.
Примечание
Twig также поддерживает побитовые операторы (b-and, b-xor, и b-or).
Примечание
Операторы чувствительны к регистру.
Сравнения
В любом выражении поддерживаются следующие операторы сравнения: ==, !=, <, >, >=, и <=.
Вы также можете проверить, является ли строка starts with или ends with другой строкой:
{% if 'Fabien' starts with 'F' %}
{% endif %}
{% if 'Fabien' ends with 'n' %}
{% endif %}
Примечание
Для сложных строковых сравнений оператор matches позволяет использовать регулярные выражения:
{% if phone matches '/^[\\d\\.]+$/' %}
{% endif %}
Оператор включения
Оператор in выполняет проверку включения. Он возвращает true если левый операнд содержится в правом:
{# returns true #}
{{ 1 in [1, 2, 3] }}
{{ 'cd' in 'abcde' }}
Подсказка
Вы можете использовать этот фильтр для выполнения проверки включения для строк, массивов или объектов, реализующих интерфейс Traversable.
Чтобы выполнить отрицательную проверку, используйте оператор not in:
{% if 1 not in [1, 2, 3] %}
{# is equivalent to #}
{% if not (1 in [1, 2, 3]) %}
Оператор проверки
Оператор is выполняет проверки. Проверки могут быть использованы для проверки переменной по отношению к общему выражению. Правый операнд — это имя проверки:
{# find out if a variable is odd #}
{{ name is odd }}
Проверки также могут принимать аргументы:
{% if post.status is constant('Post::PUBLISHED') %}
Проверки могут быть инвертированы с помощью оператора is not:
{% if post.status is not constant('Post::PUBLISHED') %}
{# is equivalent to #}
{% if not (post.status is constant('Post::PUBLISHED')) %}
Перейдите на страницу тестов, чтобы узнать больше о встроенных проверках.
Другие операторы
Следующие операторы не подходят ни под одну из других категорий:
-
|: Применяет фильтр. -
..: Создаёт последовательность на основе операнда перед и после оператора (это синтаксический сахар для функции range):{{ 1..5 }} {# equivalent to #} {{ range(1, 5) }}
Обратите внимание, что вам необходимо использовать скобки при объединении его с оператором фильтра из-за правил приоритета операторов:
(1..5)|join(', ') -
~: Преобразует все операнды в строки и конкатенирует их.{{ "Hello " ~ name ~ "!" }}вернёт (при условии, чтоnameравно'John')Hello John!. -
.,[]: Получает атрибут переменной. -
?:: Условный оператор:{{ foo ? 'yes' : 'no' }} {{ foo ?: 'no' }} is the same as {{ foo ? foo : 'no' }} {{ foo ? 'yes' }} is the same as {{ foo ? 'yes' : '' }}
-
??: Оператор слияния с null:{# returns the value of foo if it is defined and not null, 'no' otherwise #} {{ foo ?? 'no' }}
Вставка строк
Вставка строк (#{expression}) позволяет любому допустимому выражению появляться внутри строки с двойными кавычками. Результат вычисления этого выражения вставляется в строку:
{{ "foo #{bar} baz" }}
{{ "foo #{1 + 2} baz" }}
Управление пробелами
Добавлен в версии 2.8: Управление пробелами на уровне тегов было добавлено в Twig 2.8.
Первая новая строка после тега шаблона автоматически удаляется (как в PHP). Пробелы не изменяются движком шаблонов, поэтому каждый пробел (пробелы, табуляции, новые строки и т. д.) возвращается без изменений.
Вы также можете управлять пробелами на уровне тега. Используя модификаторы управления пробелами для ваших тегов, вы можете обрезать начальные и конечные пробелы.
Twig поддерживает два модификатора:
-
Обрезка пробелов с помощью модификатора
-: Удаляет все пробелы (включая новые строки); -
Обрезка пробелов в строке с помощью модификатора
~: Удаляет все пробелы (исключая новые строки). Использование этого модификатора справа отключает стандартное удаление первой новой строки, унаследованной от PHP.
Модификаторы могут быть использованы с любой стороны тегов, как в {%- или -%}, и они потребляют все пробелы для этой стороны тега. Можно использовать модификаторы с одной стороны тега или с обеих сторон:
{% 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:
{% apply spaceless %}
<div>
<strong>foo bar</strong>
</div>
{% endapply %}
{# output will be <div><strong>foo bar</strong></div> #}
Тег apply был представлен в Twig 2.9; используйте тег filter для предыдущих версий.
Расширения
Twig можно расширять. Если вы хотите создать свои собственные расширения, прочитайте главу Создание расширения.
© 2009–2018 by the Twig Team
Licensed under the three clause BSD license.
The Twig logo is © 2010–2020 Symfony
https://twig.symfony.com/doc/2.x/templates.html