是否有任何方法可以从 Twig 模板中发现所需的变量?例如,如果我有:
Hello {{ user }}! You're {{ age }} years old, well done big man!
我将能够加载这个模板,然后收集每个必需的变量,最终让我有类似的东西:
Array ( [0] => user [1] => age )
这样做的最终目标是能够定义一个视图,然后让系统根据模板文件中的所需变量创建一个表单。
是否有任何方法可以从 Twig 模板中发现所需的变量?例如,如果我有:
Hello {{ user }}! You're {{ age }} years old, well done big man!
我将能够加载这个模板,然后收集每个必需的变量,最终让我有类似的东西:
Array ( [0] => user [1] => age )
这样做的最终目标是能够定义一个视图,然后让系统根据模板文件中的所需变量创建一个表单。
工作解决方案
感谢 morg 指出我tokenize
能够使用以下内容获得我想要的东西(我将它放在我的控制器中进行测试):
$lexer = new \Twig_Lexer(new \Twig_Environment());
$stream = $lexer->tokenize(new \Twig_Source('{{test|raw}}{{test2|raw|asd}}{{another}}{{help_me}}', null));
$variables = array();
while (!$stream->isEOF()) {
$token = $stream->next();
if($token->getType() === \Twig_Token::NAME_TYPE){
$variables[] = $token->getValue();
while (!$stream->isEOF() && $token->getType() !== \Twig_Token::VAR_END_TYPE) {
$token = $stream->next();
}
}
}
$variables = array_unique($variables);
这将返回:
Array
(
[0] => test
[1] => test2
[2] => another
[3] => help_me
)
你会注意到我只得到变量而不是任何函数(这是通过设计),但如果你想同时得到变量和函数,你可以删除嵌套的 while 循环。
您可以为此使用 twig 标记器。
$stream = $twig->tokenize($source, $identifier);
标记器有一个toString()
方法,您可以解析其结果字符串
VAR_START_TYPE()
NAME_TYPE(varname)
VAR_END_TYPE()
查看此内容以获取更多详细信息。
您可以尝试使用preg_match_all('{{\s*(\w+)\s*}}', 'template {{string }} with {{ var}}', $matchesArray);
. 其$matchArray
结构如下:
Array(
0 => array(0 => '{{string }}', 1 => 'string'),
1 => array(0 => '{{ var}}', 1 => 'var')
)
从 PHP 代码中执行此操作的另一种方法并不优雅,但仍然比任何正则表达式更可靠:
$source = "My template string with {{ some }} parameters.";
$stream = $twig->tokenize(new \Twig_Source($source, "source"));
$matches = [];
preg_match_all(
"/NAME_TYPE\((.*)\)/", $stream->__toString(), $matches
);
if (count($matches) > 1) {
$params = array_unique($matches[1]);
} else {
$params = [];
}
这通过使用 Twig 内部机制来标记模板字符串,然后使用正则表达式提取参数名称来工作。
编辑:我的答案的先前版本使用 parse 方法来创建节点树,但它似乎不再起作用,并且在上一步中匹配 NAME_TYPE 似乎更可靠,不确定我是否错过了那里的东西......< /p>