考虑以下因素:
A) {{ form.vars.attr.dimensions.width * .1875 }}
B) {{ form.vars.attr.dimensions.width * 0.1875 }}
其中 form.vars.attr.dimensions.width
是一个整数。
以下是 form.vars.attr.dimensions
的转储。
array:2 [
"width" => 1600
"height" => 478
]
示例 A 将抛出以下异常:
Unexpected token "punctuation" of value ".".
示例 B 工作正常并输出 300.0
。
我知道它很可能将值解释为字符串,但我的问题是为什么?我认为,由于它没有被引用,所以它不应该被视为字面意思。我意识到我可以用 number_format、前面的零等来解决这个问题。我真的很好奇为什么 Twig 不能正确识别该小数。或者也许我还遗漏了其他东西。
此外,在普通 PHP 中应用相同的逻辑不会产生这种情况:
<?php
$val = 1600;
var_dump($val * .1875);
// float(300)
?>
最佳答案
.1875
中的.
在模板渲染的第一步中已经被识别为标点符号。
Twig 文档在 Twig Internals 中介绍了此过程。 。第一步:
The lexer tokenizes a template source code into a token stream
在文档部分The Lexer ,它展示了一种将某些源代码转换为 token 流的方法。如果我们用你的两个例子来做到这一点:
$ex1 = '{{ form.vars.attr.dimensions.width * 0.1875 }}';
$ex2 = '{{ form.vars.attr.dimensions.width * .1875 }}';
$stream1 = $twig->tokenize(new Twig_Source($ex1, 'example1'));
$stream2 = $twig->tokenize(new Twig_Source($ex2, 'example2'));
输出如下:
Example 1: Example 2:
VAR_START_TYPE() VAR_START_TYPE()
NAME_TYPE(form) NAME_TYPE(form)
PUNCTUATION_TYPE(.) PUNCTUATION_TYPE(.)
NAME_TYPE(vars) NAME_TYPE(vars)
PUNCTUATION_TYPE(.) PUNCTUATION_TYPE(.)
NAME_TYPE(attr) NAME_TYPE(attr)
PUNCTUATION_TYPE(.) PUNCTUATION_TYPE(.)
NAME_TYPE(dimensions) NAME_TYPE(dimensions)
PUNCTUATION_TYPE(.) PUNCTUATION_TYPE(.)
NAME_TYPE(width) NAME_TYPE(width)
OPERATOR_TYPE(*) OPERATOR_TYPE(*)
NUMBER_TYPE(0.1875) PUNCTUATION_TYPE(.) <----
VAR_END_TYPE() NUMBER_TYPE(1875)
EOF_TYPE() VAR_END_TYPE()
EOF_TYPE()
在该过程的下一步中,解析器尝试将标记流转换为树,并且标点符号标记在运算符之后没有意义,这会导致您看到的错误。
至于为什么 Twig 词法分析器在第一步中以这种方式工作,如果您检查 the source ,表达式词法分析器逐步遍历输入字符串,依次应用各种正则表达式。数字正则表达式是
'/[0-9]+(?:\.[0-9]+)?/A'
与 .1875
不匹配,在后续步骤中,.
被识别为标点符号。
如果您试图找出一种方法让它使用不带前导零的十进制数字,那么这个答案没有帮助,但听起来您更感兴趣的是了解它是如何工作的,所以希望这个会有帮助的。
关于php - 当小数前面没有数值时, Twig 假设标点符号/字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47042126/