Twig для разработчиков
В этом разделе описывается API Twig, а не язык шаблонов. Он будет наиболее полезен в качестве справочника для тех, кто реализует интерфейс шаблонов для приложения, а не для тех, кто создаёт Twig-шаблоны.
Основы
Twig использует центральный объект, называемый средой (класса \Twig\Environment). Экземпляры этого класса используются для хранения конфигурации и расширений, а также для загрузки шаблонов.
Большинство приложений создают один объект \Twig\Environment при инициализации приложения и используют его для загрузки шаблонов. В некоторых случаях может быть полезно иметь несколько сред, работающих бок о бок с различными конфигурациями.
Типичный способ настройки Twig для загрузки шаблонов для приложения выглядит примерно так:
require_once '/path/to/vendor/autoload.php';
$loader = new \Twig\Loader\FilesystemLoader('/path/to/templates');
$twig = new \Twig\Environment($loader, [
'cache' => '/path/to/compilation_cache',
]);
Это создаёт среду шаблонов с конфигурацией по умолчанию и загрузчиком, который ищет шаблоны в каталоге /path/to/templates/. Доступны различные загрузчики, и вы также можете написать свой собственный, если хотите загружать шаблоны из базы данных или других ресурсов.
Примечание
Обратите внимание, что второй аргумент среды — это массив параметров. Параметр cache — это каталог кэша компиляции, где Twig кеширует скомпилированные шаблоны, чтобы избежать фазы разбора для последующих запросов. Он сильно отличается от кэша, который вы можете добавить для вычисленных шаблонов. Для такой задачи можно использовать любую доступную PHP-библиотеку кэширования.
Отображение шаблонов
Для загрузки шаблона из среды Twig вызовите метод load(), который возвращает экземпляр \Twig\TemplateWrapper.
$template = $twig->load('index.html');
Примечание
До версии Twig 1.28 используйте loadTemplate() вместо него, который возвращает экземпляр \Twig\Template.
Для отображения шаблона с некоторыми переменными, вызовите метод render().
echo $template->render(['the' => 'variables', 'go' => 'here']);
Примечание
Метод display() является сокращением для вывода отрендеренного шаблона.
Вы также можете загрузить и отобразить шаблон в одном шаге:
echo $twig->render('index.html', ['the' => 'variables', 'go' => 'here']);
Добавлен в версии 1.28: Возможность отображения блоков из API была добавлена в Twig 1.28.
Если шаблон определяет блоки, их можно отобразить индивидуально с помощью вызова renderBlock().
echo $template->renderBlock('block_name', ['the' => 'variables', 'go' => 'here']);
Параметры среды
При создании нового экземпляра \Twig\Environment, вы можете передать массив параметров в качестве второго аргумента конструктора:
$twig = new \Twig\Environment($loader, ['debug' => true]);
Доступны следующие параметры:
-
debugлогический типЕсли установлено в
true, сгенерированные шаблоны имеют метод__toString(), который можно использовать для отображения сгенерированных узлов (по умолчаниюfalse). -
charsetстрока (по умолчаниюutf-8)Кодировка символов, используемая шаблонами.
-
base_template_classстрока (по умолчанию\Twig\Template)Базовый класс шаблона для использования в сгенерированных шаблонах.
-
cacheстрока илиfalseАбсолютный путь для хранения скомпилированных шаблонов или
false, чтобы отключить кеширование (по умолчанию). -
auto_reloadлогический типПри разработке с Twig полезно перекомпилировать шаблон всякий раз, когда изменяется исходный код. Если вы не зададите значение для параметра
auto_reload, оно будет определено автоматически на основе значенияdebug. -
strict_variablesлогический типЕсли установлено в
false, Twig будет игнорировать недействительные переменные (переменные и/или атрибуты/методы, которые не существуют) и заменять их значениемnull. При установке вtrue, Twig вместо этого выбросит исключение (по умолчаниюfalse). -
autoescapeстрока или логический типЕсли установлено в
true, HTML-автоэкранирование будет включено по умолчанию для всех шаблонов (по умолчаниюtrue).Начиная с Twig 1.8, можно установить используемую стратегию экранирования (
html,js,falseдля отключения).Начиная с Twig 1.9, можно установить используемую стратегию экранирования (
css,url,html_attr, или PHP-обратный вызов, который принимает имя шаблона и должен вернуть используемую стратегию экранирования — обратный вызов не может быть именем функции, чтобы избежать конфликта со встроенными стратегиями экранирования).Начиная с Twig 1.17, стратегия экранирования
filename(переименована вnameначиная с Twig 1.27) определяет используемую стратегию экранирования для шаблона на основе расширения имени файла шаблона (эта стратегия не вносит никаких накладных расходов во время выполнения, так как автоэкранирование выполняется во время компиляции). -
optimizationsцелое числоФлаг, указывающий, какие оптимизации применять (по умолчанию
-1— все оптимизации включены; установите в0, чтобы отключить).
Загрузчики
Загрузчики отвечают за загрузку шаблонов из ресурсов, таких как файловая система.
Кэш компиляции
Все загрузчики шаблонов могут кэшировать скомпилированные шаблоны на файловой системе для последующего использования. Это значительно ускоряет Twig, так как шаблоны компилируются только один раз.
Встроенные загрузчики
Вот список встроенных загрузчиков:
\Twig\Loader\FilesystemLoader
Добавлен в версии 1.10: prependPath() и поддержка пространств имён были добавлены в Twig 1.10.
Добавлен в версии 1.27: Поддержка относительных путей была добавлена в Twig 1.27.
\Twig\Loader\FilesystemLoader загружает шаблоны из файловой системы. Этот загрузчик может находить шаблоны в папках на файловой системе и является предпочтительным способом их загрузки:
$loader = new \Twig\Loader\FilesystemLoader($templateDir);
Он также может искать шаблоны в массиве каталогов:
$loader = new \Twig\Loader\FilesystemLoader([$templateDir1, $templateDir2]);
С такой конфигурацией Twig сначала будет искать шаблоны в $templateDir1, а если их не найдёт, то обратится к $templateDir2.
Вы можете добавить или добавить пути с помощью методов addPath() и prependPath().
$loader->addPath($templateDir3);
$loader->prependPath($templateDir4);
Загрузчик файловой системы также поддерживает шаблоны с именами пространств имён. Это позволяет группировать шаблоны в различных пространствах имён, которые имеют свои собственные пути к шаблонам.
При использовании методов setPaths(), addPath(), и prependPath(), укажите пространство имён в качестве второго аргумента (если оно не указано, эти методы работают с основным пространством имён):
$loader->addPath($templateDir, 'admin');
К шаблонам с именами пространств имён можно получить доступ с помощью специальной нотации @namespace_name/template_path.
$twig->render('@admin/index.html', []);
\Twig\Loader\FilesystemLoader поддерживает абсолютные и относительные пути. Использование относительных путей предпочтительнее, так как оно делает ключи кэша независимыми от корневого каталога проекта (например, это позволяет разогреть кэш с сервера сборки, где каталог может отличаться от того, который используется на серверах производства):
$loader = new \Twig\Loader\FilesystemLoader('templates', getcwd().'/..');
Примечание
Если корневой путь не передаётся в качестве второго аргумента, Twig использует getcwd() для относительных путей.
\Twig\Loader\ArrayLoader
\Twig\Loader\ArrayLoader загружает шаблон из массива PHP. Ему передаётся массив строк, связанных с именами шаблонов:
$loader = new \Twig\Loader\ArrayLoader([
'index.html' => 'Hello {{ name }}!',
]);
$twig = new \Twig\Environment($loader);
echo $twig->render('index.html', ['name' => 'Fabien']);
Этот загрузчик очень полезен для тестирования модулей. Он также может быть использован для небольших проектов, где хранение всех шаблонов в одном PHP-файле может иметь смысл.
Подсказка
При использовании загрузчиков Array с механизмом кэширования вы должны знать, что новый ключ кэша генерируется каждый раз, когда содержимое шаблона «изменяется» (ключ кэша — это исходный код шаблона). Если вы не хотите, чтобы ваш кэш разросся, вам нужно позаботиться об очистке старых файлов кэша самостоятельно.
\Twig\Loader\ChainLoader
\Twig\Loader\ChainLoader делегирует загрузку шаблонов другим загрузчикам:
$loader1 = new \Twig\Loader\ArrayLoader([
'base.html' => '{% block content %}{% endblock %}',
]);
$loader2 = new \Twig\Loader\ArrayLoader([
'index.html' => '{% extends "base.html" %}{% block content %}Hello {{ name }}{% endblock %}',
'base.html' => 'Will never be loaded',
]);
$loader = new \Twig\Loader\ChainLoader([$loader1, $loader2]);
$twig = new \Twig\Environment($loader);
При поиске шаблона Twig пробует каждый загрузчик по очереди и возвращает результат как только шаблон найден. При отображении шаблона index.html из приведённого выше примера Twig загрузит его с помощью $loader2, но шаблон base.html будет загружен из $loader1.
Примечание
Вы также можете добавить загрузчики с помощью метода addLoader().
Создайте свой собственный загрузчик
Все загрузчики реализуют \Twig\Loader\LoaderInterface.
interface Twig_LoaderInterface
{
/**
* Gets the source code of a template, given its name.
*
* @param string $name string The name of the template to load
*
* @return string The template source code
*
* @deprecated since 1.27 (to be removed in 2.0), implement \Twig\Loader\SourceContextLoaderInterface
*/
function getSource($name);
/**
* Gets the cache key to use for the cache for a given template name.
*
* @param string $name string The name of the template to load
*
* @return string The cache key
*/
function getCacheKey($name);
/**
* Returns true if the template is still fresh.
*
* @param string $name The template name
* @param timestamp $time The last modification time of the cached template
*/
function isFresh($name, $time);
}
Метод isFresh() должен вернуть true, если текущий кэшированный шаблон всё ещё свеж, учитывая время последнего изменения, или false в противном случае.
Примечание
Начиная с Twig 1.27, вы также должны реализовать \Twig\Loader\SourceContextLoaderInterface, чтобы избежать предупреждений об устаревании.
Подсказка
Начиная с Twig 1.11.0, вы также можете реализовать \Twig\Loader\ExistsLoaderInterface, чтобы сделать ваш загрузчик быстрее при использовании с загрузчиком цепочки.
Использование расширений
Расширения Twig — это пакеты, которые добавляют новые возможности в Twig. Зарегистрируйте расширение с помощью метода addExtension().
$twig->addExtension(new \Twig\Extension\SandboxExtension());
Twig поставляется со следующими расширениями:
- TwigExtensionCoreExtension: Определяет все основные функции Twig.
-
TwigExtensionDebugExtension: Определяет функцию
dumpдля отладки переменных шаблона. - TwigExtensionEscaperExtension: Добавляет автоматическую экранировку вывода и возможность экранировать/ра экранировать блоки кода.
- TwigExtensionSandboxExtension: Добавляет режим песочницы для стандартной среды Twig, делая её безопасной для оценки небезопасного кода.
- TwigExtensionProfilerExtension: Включает встроенный профайлер Twig (начиная с Twig 1.18).
- TwigExtensionOptimizerExtension: Оптимизирует дерево узлов перед компиляцией.
-
-
TwigExtensionStringLoaderExtension: Определяет функцию
template_from_string - для загрузки шаблонов из строки в шаблоне.
-
TwigExtensionStringLoaderExtension: Определяет функцию
Расширения Core, Escaper и Optimizer регистрируются по умолчанию.
Встроенные расширения
В этом разделе описаны функции, добавленные встроенными расширениями.
Подсказка
Прочитайте главу о расширении Twig, чтобы узнать, как создать собственные расширения.
Расширение ядра
Расширение core определяет все основные функции Twig:
Расширение экранирования
Расширение escaper добавляет автоматическую экранировку вывода в Twig. Оно определяет тег autoescape и фильтр raw.
При создании расширения экранирования вы можете включить или выключить глобальную стратегию экранирования вывода:
$escaper = new \Twig\Extension\EscaperExtension('html');
$twig->addExtension($escaper);
Если установлено значение html, все переменные в шаблонах экранируются (используя стратегию экранирования html), за исключением тех, которые используют фильтр raw.
{{ article.to_html|raw }}
Вы также можете изменить режим экранирования локально, используя тег autoescape (см. документацию autoescape для синтаксиса, используемого до Twig 1.8):
{% autoescape 'html' %}
{{ var }}
{{ var|raw }}{# var won't be escaped #}
{{ var|escape }}{# var won't be double-escaped #}
{% endautoescape %}
Предупреждение
Тег autoescape не оказывает влияния на включённые файлы.
Правила экранирования реализованы следующим образом:
-
Литералы (целые числа, булевы значения, массивы и т.д.) используемые в шаблоне непосредственно в качестве переменных или аргументов фильтров, никогда автоматически не экранируются:
{{ "Twig<br/>" }} {# won't be escaped #} {% set text = "Twig<br/>" %} {{ text }} {# will be escaped #}
-
Выражения, результат которых — литерал или переменная, отмеченная как безопасная, никогда автоматически не экранируются:
{{ foo ? "Twig<br/>" : "<br/>Twig" }} {# won't be escaped #} {% set text = "Twig<br/>" %} {{ true ? text : "<br/>Twig" }} {# will be escaped #} {{ false ? text : "<br/>Twig" }} {# won't be escaped #} {% set text = "Twig<br/>" %} {{ foo ? text|raw : "<br/>Twig" }} {# won't be escaped #}
-
Экранирование применяется перед печатью, после применения любых других фильтров:
{{ var|upper }}{# is equivalent to {{ var|upper|escape }} #}
-
Фильтр raw следует использовать только в конце цепочки фильтров:
{{ var|raw|upper }}{# will be escaped #} {{ var|upper|raw }}{# won't be escaped #}
-
Автоматическая экранировка не применяется, если последний фильтр в цепочке отмечен как безопасный для текущего контекста (например,
htmlилиjs).escapeиescape('html')отмечены как безопасные для HTML,escape('js')— безопасные для JavaScript, аraw— для всего.{% autoescape 'js' %} {{ var|escape('html') }}{# will be escaped for HTML and JavaScript #} {{ var }}{# will be escaped for JavaScript #} {{ var|escape('js') }}{# won't be double-escaped #} {% endautoescape %}
Примечание
Обратите внимание, что автоматическое экранирование имеет некоторые ограничения, так как экранирование применяется к выражениям после оценки. Например, при работе со конкатенацией, {{ foo|raw ~ bar }} не даст ожидаемого результата, так как экранирование применяется к результату конкатенации, а не к отдельным переменным (поэтому фильтр raw здесь не будет иметь никакого эффекта).
Расширение песочницы
Расширение sandbox может использоваться для оценки небезопасного кода. Доступ к небезопасным атрибутам и методам запрещён. Безопасность песочницы управляется экземпляром политики. По умолчанию Twig поставляется с одним классом политики: \Twig\Sandbox\SecurityPolicy. Этот класс позволяет вам добавить в белый список некоторые теги, фильтры, свойства и методы:
$tags = ['if'];
$filters = ['upper'];
$methods = [
'Article' => ['getTitle', 'getBody'],
];
$properties = [
'Article' => ['title', 'body'],
];
$functions = ['range'];
$policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions);
С предыдущей конфигурацией, политика безопасности позволит использовать только тег if, и фильтр upper. Кроме того, шаблоны смогут вызывать методы getTitle() и getBody() на объектах Article, и публичные свойства title и body. Всё остальное будет запрещено и вызовет исключение \Twig\Sandbox\SecurityError.
Объект политики — первый аргумент конструктора песочницы:
$sandbox = new \Twig\Extension\SandboxExtension($policy);
$twig->addExtension($sandbox);
По умолчанию режим песочницы отключен и должен быть включён при включении небезопасного кода шаблона с помощью тега sandbox.
{% sandbox %}
{% include 'user.html' %}
{% endsandbox %}
Вы можете поместить все шаблоны в песочницу, передав true в качестве второго аргумента конструктора расширения:
$sandbox = new \Twig\Extension\SandboxExtension($policy, true);
Расширение профайлера
Новое в версии 1.18: Расширение профайлера было добавлено в Twig 1.18.
Расширение profiler включает профайлер для Twig-шаблонов; его следует использовать только на ваших машинах разработки, так как оно добавляет некоторую нагрузку:
$profile = new \Twig\Profiler\Profile();
$twig->addExtension(new \Twig\Extension\ProfilerExtension($profile));
$dumper = new \Twig\Profiler\Dumper\TextDumper();
echo $dumper->dump($profile);
Профиль содержит информацию о времени и потреблении памяти для выполнения шаблонов, блоков и макросов.
Вы также можете выгрузить данные в формате, совместимом с Blackfire.io:
$dumper = new \Twig\Profiler\Dumper\BlackfireDumper();
file_put_contents('/path/to/profile.prof', $dumper->dump($profile));
Загрузите профиль, чтобы просмотреть его (сначала создайте бесплатную учётную запись):
blackfire --slot=7 upload /path/to/profile.prof
Расширение оптимизатора
Расширение optimizer оптимизирует дерево узлов перед компиляцией:
$twig->addExtension(new \Twig\Extension\OptimizerExtension());
По умолчанию все оптимизации включены. Вы можете выбрать те, которые хотите включить, передав их в конструктор:
$optimizer = new \Twig\Extension\OptimizerExtension(\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR);
$twig->addExtension($optimizer);
Twig поддерживает следующие оптимизации:
-
\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_ALL, включает все оптимизации (это значение по умолчанию). -
\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_NONE, отключает все оптимизации. Это уменьшает время компиляции, но может увеличить время выполнения и потребление памяти. -
\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR, оптимизирует тегforпутём удаления создания переменнойloopпри возможности. -
\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER, удаляет фильтрrawпри возможности. -
\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_VAR_ACCESS, упрощает создание и доступ к переменным в скомпилированных шаблонах при возможности.
Исключения
Twig может вызывать исключения:
-
\Twig\Error\Error: Базовое исключение для всех ошибок. -
\Twig\Error\SyntaxError: Выбрасывается, чтобы сообщить пользователю, что есть проблема с синтаксисом шаблона. -
\Twig\Error\RuntimeError: Выбрасывается, когда возникает ошибка во время выполнения (например, когда фильтра не существует). -
\Twig\Error\LoaderError: Выбрасывается, когда возникает ошибка при загрузке шаблона. -
\Twig\Sandbox\SecurityError: Выбрасывается, когда вызывается недопустимый тег, фильтр или метод в шаблоне в режиме песочницы.
© 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/api.html