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
- Vim через плагин синтаксиса Jinja или плагин vim-twig
- Netbeans через плагин синтаксиса Twig (до версии 7.1, встроенный начиная с 7.2)
- PhpStorm (встроенный начиная с версии 2.1)
- Eclipse через плагин Twig
- Sublime Text через пакет Twig
- GtkSourceView через определение языка Twig (используется gedit и другими проектами)
- Coda и SubEthaEdit через режим синтаксиса Twig
- Coda 2 через другой режим синтаксиса Twig
- Komodo и Komodo Edit через режим подсветки/проверки синтаксиса Twig
- Notepad++ через Notepad++ Twig Highlighter
- Emacs через web-mode.el
- Atom через PHP-twig для atom
- Visual Studio Code через пакет Twig
Также, TwigFiddle — это онлайн-сервис, который позволяет выполнять шаблоны Twig из браузера; он поддерживает все версии Twig.
Переменные
Приложение передаёт переменные в шаблоны для обработки в нём. Переменные могут также иметь атрибуты или элементы, к которым можно получить доступ. Визуальное представление переменной сильно зависит от приложения, которое её предоставляет.
Используйте точку (.) для доступа к атрибутам переменной (методы или свойства PHP объекта, или элементы PHP массива):
{{ foo.bar }}
Примечание
Важно помнить, что фигурные скобки не являются частью переменной, а частью оператора вывода. При доступе к переменным внутри тегов фигурные скобки не ставьте.
Если переменная или атрибут не существуют, вы получите значение null, когда параметр strict_variables установлен в 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 1.40; используйте тег filter в предыдущих версиях.
Функции
Функции могут вызываться для генерации содержимого. Функции вызываются по их имени, за которым следуют скобки (()) и могут иметь аргументы.
Например, функция range возвращает список, содержащий арифметическую прогрессию целых чисел:
{% for i in range(0, 3) %}
{{ i }},
{% endfor %}
Перейдите на страницу функций, чтобы узнать больше о встроенных функциях.
Именованные аргументы
Введено в версии 1.12: Поддержка именованных аргументов была добавлена в Twig 1.12.
{% 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.
Макросы
Добавлена в версии 1.12: Поддержка значений по умолчанию для аргументов была добавлена в Twig 1.12.
Макросы сравнимы с функциями в обычных языках программирования. Они полезны для повторного использования фрагментов 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 #}
Литералы
Добавлена в версии 1.5: Поддержка ключей хеша в качестве имён и выражений была добавлена в Twig 1.5.
Самой простой формой выражений являются литералы. Литералы — это представления типов 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) -- as of Twig 1.5 #} { 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) -- as of Twig 1.5 #} {% 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')) %}
Перейдите на страницу тестов, чтобы узнать больше о встроенных проверках.
Другие операторы
Новое в версии 1.12.0: Поддержка расширенного тернарного оператора была добавлена в Twig 1.12.0.
Следующие операторы не подходят ни к одной из других категорий:
-
|: Применяет фильтр. -
..: Создаёт последовательность, основанную на операндах до и после оператора (это синтаксический сахар для функции range):{{ 1..5 }} {# equivalent to #} {{ range(1, 5) }}
Обратите внимание, что при комбинировании с оператором фильтра необходимо использовать скобки из-за правил приоритета операторов:
(1..5)|join(', ') -
~: Преобразует все операнды в строки и конкатенирует их.{{ "Hello " ~ name ~ "!" }}вернёт (при условии, чтоnameесть'John')Hello John!. -
.,[]: Получает атрибут переменной. -
?:: Тернарный оператор:{{ foo ? 'yes' : 'no' }} {# as of Twig 1.12.0 #} {{ 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' }}
Интерполяция строк
Новое в версии 1.5: Интерполяция строк была добавлена в Twig 1.5.
Интерполяция строк (#{expression}) позволяет любому допустимому выражению появляться внутри строки с двойными кавычками. Результат вычисления этого выражения вставляется в строку:
{{ "foo #{bar} baz" }}
{{ "foo #{1 + 2} baz" }}
Управление пробелами
Новое в версии 1.1: Управление пробелами на уровне тегов было добавлено в Twig 1.1.
Новое в версии 1.39: Управление пробелами на уровне строк тегов было добавлено в Twig 1.39.
Первая новая строка после тега шаблона автоматически удаляется (как в 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 1.40; используйте тег 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/1.x/templates.html