Внутреннее устройство Twig
Twig очень расширяем, и вы можете его модифицировать. Имейте в виду, что вам, вероятно, стоит сначала создать расширение, а не изменять ядро, так как большинство функций и улучшений можно реализовать с помощью расширений. Эта глава также полезна для тех, кто хочет понять, как работает Twig внутри.
Как работает Twig?
Вывод шаблона Twig можно свести к четырём ключевым шагам:
-
Загрузка шаблона: Если шаблон уже скомпилирован, загрузите его и перейдите к шагу оценки, в противном случае:
- Сначала лексер разбивает исходный код шаблона на мелкие фрагменты для более удобной обработки;
- Затем парсер преобразует поток токенов в осмысленное дерево узлов (дерево абстрактного синтаксиса);
- Наконец, компилятор преобразует дерево абстрактного синтаксиса в код PHP.
-
Оценивание шаблона: Это означает вызов метода
display()скомпилированного шаблона и передачу ему контекста.
Лексер
Лексер разбивает исходный код шаблона на поток токенов (каждый токен — это экземпляр \Twig\Token, а поток — экземпляр \Twig\TokenStream). Стандартный лексер распознаёт 13 различных типов токенов:
-
\Twig\Token::BLOCK_START_TYPE,\Twig\Token::BLOCK_END_TYPE: Разделители блоков ({% %}) -
\Twig\Token::VAR_START_TYPE,\Twig\Token::VAR_END_TYPE: Разделители переменных ({{ }}) -
\Twig\Token::TEXT_TYPE: Текст вне выражения; -
\Twig\Token::NAME_TYPE: Имя в выражении; -
\Twig\Token::NUMBER_TYPE: Число в выражении; -
\Twig\Token::STRING_TYPE: Строка в выражении; -
\Twig\Token::OPERATOR_TYPE: Оператор; -
\Twig\Token::PUNCTUATION_TYPE: Знак препинания; -
\Twig\Token::INTERPOLATION_START_TYPE,\Twig\Token::INTERPOLATION_END_TYPE(начиная с Twig 1.5): Разделители для интерполяции строк; -
\Twig\Token::EOF_TYPE: Конец шаблона.
Вы можете вручную преобразовать исходный код в поток токенов, вызвав метод tokenize() среды:
$stream = $twig->tokenize(new \Twig\Source($source, $identifier));
Новое в версии 1.27: \Twig\Source был добавлен в версии 1.27, в предыдущих версиях необходимо было передавать исходный код и идентификатор напрямую.
Так как поток имеет метод __toString(), вы можете получить текстовое представление, выведя объект:
echo $stream."\n";
Вот вывод для шаблона %%%CODE_BLOCK_23%%:
TEXT_TYPE(Hello )
VAR_START_TYPE()
NAME_TYPE(name)
VAR_END_TYPE()
EOF_TYPE()
Примечание
Стандартный лексер (\Twig\Lexer) может быть изменён вызовом метода %%%CODE_BLOCK_26%%:
$twig->setLexer($lexer);
Парсер
Парсер преобразует поток токенов в дерево абстрактного синтаксиса (AST) или дерево узлов (экземпляр \Twig\Node\ModuleNode). Основное расширение определяет базовые узлы, такие как: for, if, … и узлы выражений.
Вы можете вручную преобразовать поток токенов в дерево узлов, вызвав метод parse() среды:
$nodes = $twig->parse($stream);
Вывод объекта узла даст вам хорошее представление о дереве:
echo $nodes."\n";
Вот вывод для шаблона %%%CODE_BLOCK_34%%:
\Twig\Node\ModuleNode(
\Twig\Node\TextNode(Hello )
\Twig\Node\PrintNode(
\Twig\Node\Expression\NameExpression(name)
)
)
Примечание
Стандартный парсер (\Twig\TokenParser\AbstractTokenParser) может быть изменён вызовом метода %%%CODE_BLOCK_37%%:
$twig->setParser($parser);
Компилятор
Последний шаг выполняется компилятором. Он принимает дерево узлов в качестве входных данных и генерирует код PHP, пригодный для выполнения шаблона во время выполнения.
Вы можете вручную скомпилировать дерево узлов в код PHP с помощью метода compile() среды:
$php = $twig->compile($nodes);
Сгенерированный шаблон для шаблона Hello {{ name }} выглядит следующим образом (фактический вывод может отличаться в зависимости от используемой версии Twig):
/* Hello {{ name }} */
class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends \Twig\Template
{
protected function doDisplay(array $context, array $blocks = [])
{
// line 1
echo "Hello ";
echo twig_escape_filter($this->env, (isset($context["name"]) ? $context["name"] : null), "html", null, true);
}
// some more code
}
Примечание
Стандартный компилятор (\Twig\Compiler) может быть изменён вызовом метода %%%CODE_BLOCK_44%%:
$twig->setCompiler($compiler);
© 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/internals.html