PHP: 为什么“${obj->prop}”是解析错误,而“$obj->prop”是合法的?
PHP: Why is "${obj->prop}" a parsing error, while "$obj->prop" is legal?
PHP 7.3.2
在解析 PHP 的双引号字符串中的变量时,我发现有一个解析错误很奇怪:
echo "${obj->prop}"; // Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR)
// But this is legal:
echo "$obj->prop";
// And, for instance, all these are legal as well:
echo "${arr['key']}";
echo "${arr[0]}";
echo "${arr['0']}";
为什么口译员在${…}
内对->
有偏见?
首先,像这样的大括号不是复杂变量解析语法的替代形式。
"$var"
和"${var}"
是简单语法,"{$var}"
是复杂语法。
在简单的语法中,解释器严格地寻找变量名,而不是表达式,花括号仅用于指示名称的结尾,以防你有类似 "${var}othertext"
的东西。手册指出
If a dollar sign ($) is encountered, the parser will greedily take as many tokens as possible to form a valid variable name. Enclose the variable name in curly braces to explicitly specify the end of the name.
解释器并没有特别反对 ${…}
中的 ->
,实际上解释器对于它认为 ${…}
中的有效变量名是非常严格的,并且对访问进行了一次例外处理单个数组键。
你不能做 "${var['a']['b']}"
,例如。
在解释代码的第一步中,当字符串被标记化时,${
是一个标记 T_DOLLAR_OPEN_CURLY_BRACES
,它将扫描器设置为 "looking for variable name" 状态。在那种状态下,唯一会被识别为变量名的是一个有效的标签,后跟一个左方括号或右花括号。
标记数组键示例如下所示:
source: " ${ arr [ 'key' ] } "
tokens: " T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME [ T_CONSTANT_ENCAPSED_STRING ] } "
对象 属性 示例如下所示:
source: " ${ obj -> prop } "
tokens: " T_DOLLAR_OPEN_CURLY_BRACES T_STRING T_OBJECT_OPERATOR T_STRING } "
解析错误发生在下一步,将对象运算符应用于字符串,这是意外的。
使用不带大括号的简单语法,您会得到这些标记,如您所知,它们工作得很好:
source: " $obj -> prop "
tokens: " T_VARIABLE T_OBJECT_OPERATOR T_STRING "
PHP 7.3.2
在解析 PHP 的双引号字符串中的变量时,我发现有一个解析错误很奇怪:
echo "${obj->prop}"; // Parse error: syntax error, unexpected '->' (T_OBJECT_OPERATOR)
// But this is legal:
echo "$obj->prop";
// And, for instance, all these are legal as well:
echo "${arr['key']}";
echo "${arr[0]}";
echo "${arr['0']}";
为什么口译员在${…}
内对->
有偏见?
首先,像这样的大括号不是复杂变量解析语法的替代形式。
"$var"
和"${var}"
是简单语法,"{$var}"
是复杂语法。
在简单的语法中,解释器严格地寻找变量名,而不是表达式,花括号仅用于指示名称的结尾,以防你有类似 "${var}othertext"
的东西。手册指出
If a dollar sign ($) is encountered, the parser will greedily take as many tokens as possible to form a valid variable name. Enclose the variable name in curly braces to explicitly specify the end of the name.
解释器并没有特别反对 ${…}
中的 ->
,实际上解释器对于它认为 ${…}
中的有效变量名是非常严格的,并且对访问进行了一次例外处理单个数组键。
你不能做 "${var['a']['b']}"
,例如。
在解释代码的第一步中,当字符串被标记化时,${
是一个标记 T_DOLLAR_OPEN_CURLY_BRACES
,它将扫描器设置为 "looking for variable name" 状态。在那种状态下,唯一会被识别为变量名的是一个有效的标签,后跟一个左方括号或右花括号。
标记数组键示例如下所示:
source: " ${ arr [ 'key' ] } "
tokens: " T_DOLLAR_OPEN_CURLY_BRACES T_STRING_VARNAME [ T_CONSTANT_ENCAPSED_STRING ] } "
对象 属性 示例如下所示:
source: " ${ obj -> prop } "
tokens: " T_DOLLAR_OPEN_CURLY_BRACES T_STRING T_OBJECT_OPERATOR T_STRING } "
解析错误发生在下一步,将对象运算符应用于字符串,这是意外的。
使用不带大括号的简单语法,您会得到这些标记,如您所知,它们工作得很好:
source: " $obj -> prop "
tokens: " T_VARIABLE T_OBJECT_OPERATOR T_STRING "