Twig 中文文档
  • 关于
  • Twig 1.x
  • Twig 2.x
    • 介绍
    • 安装
    • Twig for 模板设计师
    • Twig for 开发者
    • 扩展 Twig
    • Twig 内部机制
    • 弃用功能
    • Twig 方法
    • 编码标准
    • API
    • 附录*核心扩展
      • 标签(Tags)
        • 自动转义 autoescape
        • 块 block
        • do
        • embed
        • extends
        • filter
        • flush
        • for
        • from
        • if
        • import
        • include
        • macro
        • sandbox
        • set
        • spaceless
        • use
        • verbatim
        • with
      • 过滤器(Filters)
        • abs
        • batch
        • capitalize
        • convert_encoding
        • date
        • date_modify
        • default
        • escape
        • first
        • format
        • join
        • json_encode
        • keys
        • last
        • length
        • lower
        • merge
        • nl2br
        • number_format
        • raw
        • replace
        • reverse
        • round
        • slice
        • sort
        • split
        • striptags
        • title
        • trim
        • upper
        • url_encode
      • 函数(Functions)
        • attribute
        • block
        • constant
        • cycle
        • date
        • dump
        • include
        • max
        • min
        • parent
        • random
        • range
        • source
        • template_from_string
      • 测试(Tests)
        • constant
        • defined
        • divisible by
        • empty
        • even
        • iterable
        • null
        • odd
        • same as
      • Operators(操作符)
  • 附录*资料整理
Powered by GitBook
On this page
  • Twig 内部机制
  • Twig是如何工作的呢?
  • Lexer
  • 解析器(Parser)
  • 编译器(Compiler)

Was this helpful?

  1. Twig 2.x

Twig 内部机制

Previous扩展 TwigNext弃用功能

Last updated 5 years ago

Was this helpful?

原文: 翻译:小虾米(QQ:509129)

Twig 内部机制

Twig是非常可扩展的,您可以轻松攻击它。请记住,您应该尝试在黑客攻击核心之前创建扩展,因为大多数特性和增强都可以通过扩展来处理。这一章也对那些想了解Twig如何在引擎盖下工作的人有用。

Twig是如何工作的呢?

Twig模板的呈现可以概括为四个关键步骤:

  • 加载模板:如果模板已经编译,加载它并进入评估步骤,否则:

    • 首先,lexer将模板源代码标记为小块,以便进行更简单的处理;

    • 然后,解析器将令牌流转换为有意义的节点树(抽象语法树);

    • 最终,编译器将AST转换为PHP代码。

  • 评估模板:它基本上意味着调用已编译模板的display()方法并将其传递给上下文。

Lexer

lexer将模板源代码标记为令牌流(每个令牌是Twig_Token的一个实例,而流是Twig_TokenStream的实例)。默认的lexer识别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::插值_start_type,Twig_Token::插值函数:字符串插值的分隔符;

  • 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()

可以通过调用setLexer()方法来更改默认的lexer(Twig_Lexer):

$twig->setLexer($lexer);

解析器(Parser)

解析器将令牌流转换为AST(抽象语法树)或节点树(Twig_Node_Module的实例)。核心扩展定义了基本的节点,例如:for,如果,…表达式节点。

通过调用环境的parse()方法,您可以手动将标记流转换为节点树:

$nodes = $twig->parse($stream);

与节点对象相呼应,可以得到树的良好表示:

echo $nodes."\n";

这里是Hello { { name }模板的输出:

Twig_Node_Module(
  Twig_Node_Text(Hello )
  Twig_Node_Print(
    Twig_Node_Expression_Name(name)
  )
)

默认解析器(Twig_TokenParser)可以通过调用setParser()方法来更改:

$twig->setParser($parser);

编译器(Compiler)

最后一步是由编译器完成的。它将节点树作为输入,并生成用于模板运行时执行的PHP代码。

您可以通过一个环境的compile()方法手工地将节点树编译为PHP代码:

$php = $twig->compile($nodes);

Hello { { name }模板的生成模板如下(根据所使用的Twig版本,实际的输出会有所不同):

/* Hello {{ name }} */
class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends Twig_Template
{
    protected function doDisplay(array $context, array $blocks = array())
    {
        // 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);
Twig Internals