Внутреннее устройство 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\Token::EOF_TYPE: Конец шаблона.
Вы можете вручную преобразовать исходный код в поток токенов, вызвав метод tokenize() среды:
$stream = $twig->tokenize(new \Twig\Source($source, $identifier));
Поскольку поток имеет метод __toString(), вы можете получить текстовое представление, выведя объект:
echo $stream."\n";
Вот вывод для шаблона Hello {{ name }}.
TEXT_TYPE(Hello )
VAR_START_TYPE()
NAME_TYPE(name)
VAR_END_TYPE()
EOF_TYPE()
Примечание
Лексер по умолчанию (\Twig\Lexer) можно изменить, вызвав метод setLexer().
$twig->setLexer($lexer);
Парсер
Парсер преобразует поток токенов в АСД (Абстрактное синтаксическое дерево), или дерево узлов (экземпляр \Twig\Node\ModuleNode). Основное расширение определяет базовые узлы, такие как: for, if, … и узлы выражений.
Вы можете вручную преобразовать поток токенов в дерево узлов, вызвав метод parse() среды:
$nodes = $twig->parse($stream);
Вывод объекта узла даст вам хорошее представление о дереве:
echo $nodes."\n";
Вот вывод для шаблона Hello {{ name }}:
\Twig\Node\ModuleNode(
\Twig\Node\TextNode(Hello )
\Twig\Node\PrintNode(
\Twig\Node\Expression\NameExpression(name)
)
)
Примечание
Парсер по умолчанию (\Twig\TokenParser\AbstractTokenParser) можно изменить, вызвав метод setParser():
$twig->setParser($parser);
Компилятор
Последний шаг выполняется компилятором. Он принимает дерево узлов как вход и генерирует PHP-код, пригодный для выполнения шаблона во время работы.
Вы можете вручную скомпилировать дерево узлов в PHP-код с помощью метода compile() среды:
$php = $twig->compile($nodes);
Сгенерированный шаблон для шаблона Hello {{ name }} выглядит следующим образом (фактический вывод может отличаться в зависимости от версии Twig, которую вы используете):
/* Hello {{ name }} */
class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends 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) можно изменить, вызвав метод setCompiler():
$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/3.x/internals.html