You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用registerUndefinedTokenParserCallback()适配Twig未知标签?

问题

扩展开源项目解析Twig文件时,需要配置Twig的Environment类,让解析器忽略未知标签但仍处理其内部节点。已通过registerUndefinedFilterCallback()和registerUndefinedFunctionCallback()成功适配未知过滤器与函数,但registerUndefinedTokenParserCallback()无法正常工作——尝试传入Token类或TokenParser类均未达到预期效果。

相关代码片段:

class TwigUtils
{
    private function __construct() {}

    /**
     * Return a factory to shim any symbols that can't be resolved in the Twig template being parsed.
     *
     * @param string $type
     * @return \Closure
     */
    public static function undefinedSymbolHandler(string $type) {
        return function ($name) use ($type) {
            return new $type($name);
        };
    }
}
...
$loader = new FilesystemLoader();
$env = new Environment($loader);

$env->registerUndefinedFilterCallback(TwigUtils::undefinedSymbolHandler(TwigFilter::class));
$env->registerUndefinedFunctionCallback(TwigUtils::undefinedSymbolHandler(TwigFunction::class));
$env->registerUndefinedTokenParserCallback(TwigUtils::undefinedSymbolHandler(Token::class));

解决方案

核心问题

registerUndefinedTokenParserCallback()要求回调返回自定义的TokenParser实例,而非Token或默认TokenParser。这个自定义TokenParser需要实现parse()方法,跳过未知标签的首尾标记,同时解析并保留标签内部的所有节点。

实现步骤

  1. 自定义PassThroughTokenParser类
    创建一个TokenParser,专门处理未知标签,仅跳过标签本身、保留内部内容解析:
use Twig\TokenParser\AbstractTokenParser;
use Twig\Token;

class PassThroughUnknownTokenParser extends AbstractTokenParser
{
    private $tagName;

    public function __construct(string $tagName)
    {
        $this->tagName = $tagName;
    }

    public function parse(Token $token)
    {
        $parser = $this->parser;
        // 跳过未知标签的开始标记及后续参数
        $parser->getStream()->skipUntil(Token::BLOCK_END_TYPE);
        $parser->getStream()->expect(Token::BLOCK_END_TYPE);

        // 解析标签内部的所有节点
        $body = $parser->subparse([$this, 'decideTagEnd'], true);

        // 跳过未知标签的结束标记
        $parser->getStream()->expect(Token::BLOCK_END_TYPE);

        // 返回包含内部节点的实例,确保内部内容被正常处理
        return new \Twig\Node\Node(['body' => $body], [], $token->getLine(), $this->tagName);
    }

    public function getTag()
    {
        return $this->tagName;
    }

    private function decideTagEnd(Token $token)
    {
        return $token->test('end'.$this->tagName);
    }
}
  1. 调整回调注册逻辑
    替换原有的TokenParser回调注册,直接返回自定义的TokenParser实例:
// 直接使用匿名函数注册回调(简洁直观)
$env->registerUndefinedTokenParserCallback(function(string $tagName) {
    return new PassThroughUnknownTokenParser($tagName);
});
  1. 验证效果
    配置完成后,Twig解析器遇到未知标签时,会自动跳过{% tag %}和{% endtag %}标记,同时正常解析标签内部的所有Twig语法(变量、过滤器、已知标签等)。

内容的提问来源于stack exchange,提问作者pecus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 05:05:18