php - Twig 自动删除撇号和引号
问题描述
TransTokenParser
为了学习(解析{% trans %}
和)->,我创建了自己{% trans with %}
的解析器,除了后一个变体之外,解析器本身运行良好:trans with
.
解析器读出分配的变量,但自动转义"
,'
因此它们不显示(变量没有'
或"
直接来自解析器)。
例如,我们在树枝中有这个块:
{% trans with {'{test}': coolFunctionWhichReturnsString('testParameter')} %}
UNIQUE_TRANS_ID
{% endtrans %}
这个块可以用 trans 和诸如此类的东西很好地解析,但是将 'with' 之后的部分变成这样: {{test}: coolFunctionWhichReturnsString(testParameter)}
我尝试在 Twig_Environment 中设置参数
new Twig_Environment(..., ['autoescape' => false])
我试过在树枝下的 config.yml 中设置一个全局变量:
autoescape: false
这两种解决方案都没有反映 twig -> php 行为的变化。(它将自动转义设置为 false,如在此处初始化 twig 环境时的 var_dump 中所示:
array (size=13)
'debug' => boolean true
'charset' => string 'UTF-8' (length=5)
'base_template_class' => string 'Twig_Template' (length=13)
'strict_variables' => boolean true
'autoescape' => boolean false
这是我的代码:
/**
* @return array
* @throws \Twig_Error_Syntax
*/
private function parseVariant(): array
{
$stream = $this->parser->getStream();
$trans = null;
$json = null;
//SIMPLE VARIANT trans
$stream->nextIf(\Twig_Token::PUNCTUATION_TYPE, '');
if (null !== $stream->nextIf(\Twig_Token::BLOCK_END_TYPE)) { //%} TRANS_LITERAL
$stream->nextIf(\Twig_Token::PUNCTUATION_TYPE, '');
$trans = $stream->expect(\Twig_Token::TEXT_TYPE)->getValue();
} elseif (null !== $stream->nextIf(\Twig_Token::NAME_TYPE, 'with')) { // {% trans with {} %} TRANS_LITERAL
$stream->next();
$json = implode($this->getInlineParams());
$stream->nextIf(\Twig_Token::PUNCTUATION_TYPE);
$stream->nextIf(\Twig_Token::BLOCK_END_TYPE);
$stream->nextIf(\Twig_Token::PUNCTUATION_TYPE);
$trans = $stream->expect(\Twig_Token::TEXT_TYPE)->getValue();
//die();
}
// {% endtrans %}
$stream->nextIf(\Twig_Token::PUNCTUATION_TYPE);
$stream->expect(\Twig_Token::BLOCK_START_TYPE);
$stream->nextIf(\Twig_Token::PUNCTUATION_TYPE);
$stream->expect(\Twig_Token::NAME_TYPE);
$stream->nextIf(\Twig_Token::PUNCTUATION_TYPE);
$endLine = $stream->expect(\Twig_Token::BLOCK_END_TYPE)->getLine();
return [$json, $trans, $endLine];
}
问题在于 $json,在这种情况下指的是:
$json = implode($this->getInlineParams());
获取内联参数:
protected function getInlineParams(): array
{
$stream = $this->parser->getStream();
$params = [];
while (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) {
$params[] = $this->parser->getStream()->next()->getValue();
}
$stream->expect(\Twig_Token::BLOCK_END_TYPE);
return $params;
}
编辑:使用 ExpressionParser 会引发错误,因为键/值没有“”或“”..
另一个编辑:我已经尝试在 twig 中修改运行时和初始化后的“转义符”扩展,包括所有策略 - 没有任何帮助
有什么建议么?提前致谢。
解决方案
这是一个双重问题:第一个可能是getInlineParams
函数中简单逻辑的一种方法,这对于这些简单的情况可能没有问题,但对于更复杂的情况可能是可怕的。
第二个问题是对类型的完全无知。
{'{test}': coolFunctionWhichReturnsString('testParameter')}
被解析为(读作“字符串值”-“令牌类型”):
{
- 块开始{test}
- 一个字符串:
- 标点符号coolFunctionWhichReturnsString
- 一个名字(
- (不确定是哪种类型)testParameter
- 一个字符串)
- (再次)}
- 块结束
当您嵌套多个 {} 时,第一个问题将展开。第二个问题是由于一个简单的事实:
类型很重要。
词法分析器有一项非常重要的任务,它删除用户可能选择表达字符串、注释的所有不同变体,它删除不相关的空格(因为它只是混乱)等等。现在,如果您将每个Token
(具有值和类型)视为只是包含您想要的字符串的一些奇怪的对象,那么您就会遇到问题 - 很明显。
因此,如果您想重新创建类似于原始输入的内容,则必须查看类型并在类型为字符串时添加引号。(文本可能是块之外的所有东西)
(这将是您陈述的问题的快速“解决方案”)
但是,从长远来看,忽略标记的语义会导致问题……因为您还必须以某种方式处理“coolFunctionWhichReturnsString”,即您必须将其转换为一些函数调用。从理论上讲,您应该真正构建一个 AST 并在某个时候将其编译成适当的形式......
树枝解析器使用一种方法subparse
来解析东西,直到出现一些“结束”。(建立一个 AST,因为结构在某些时候也很重要)
更新:事实证明,在 twig 文档中有一个用于编写节点解析器的页面,如果您遵循https://twig.symfony.com/doc/2.x/advanced.html ,它可能会大大简化这一点#registering-a-new-tag(信息从“注册新标签”开始略高于“注册新标签”,大大简化了值的解析和使用)
推荐阅读
- aws-lambda - Should I create database update function outside of amplify?
- javascript - PostMan 使用 Laravel 获取 JWT 的预请求脚本
- c# - 分离 NpgsqlConnection 的关注点
- wcf - 如何将 Application Insights 添加到 ILogger
将 Unity DI 用于 WCF 服务 - c++ - C++20:从给定的可变参数类型生成类型
- html - 如何获取 REST API 数据并在 html 页面中显示
- doctrine-orm - 原则防止数据库中不存在记录的 OneToOne 关联错误
- c# - 如何创建原始文件以获取字节数组?
- data-structures - 如何以定义明确的非自定义格式编写小数
- wordpress - Wordpress 多站点 Htaccess 覆盖