空合并运算符有一个与 PHP 中的大多数其他比较器不同的先例:
示例 1:
(错误)
$var['x'] = "5";
if ((int)$var['x']??0 < 1 ) {
print "less than 1"; /* outputs this */
}
else {
print "more than 1";
}
这将导致“ less
”,因为比较似乎是在$var['x']
vs之间0<1
,但这肯定会是,但$var['x']??(false)
在我看来,这仍然不能保证这if
是真的。
示例 2:
(错误)
$var['x'] = "5";
if ($var['x']??5 < 1 ) {
print "less than 1"; /* still outputs this */
}
else {
print "more than 1";
}
我确实理解预期的输出;但我不明白PHP 为达到其选择的结论所采取的步骤。
我已经阅读了https://www.php.net/manual/en/language.operators.precedence.php和PHP 短三元(“Elvis”)运算符与空合并运算符,但这些并没有明确概述我认为示例 1 和示例 2 中出现意外行为的原因。
哪些逻辑处理步骤导致其以这种方式工作?
示例 3:
( 正确的 )
$var['x'] = "5";
if ((int)($var['x']??0) < 1 ) {
print "less than 1";
}
else {
print "more than 1";
}
这将产生正确的“ more
”输出。
这里的关键问题是运算符优先级。在 PHP 中,强制类型转换运算符
(int)
和比较运算符的<
优先级都高于空合并运算符??
。这意味着在您的第一个示例中PHP 会按照如下方式解释该表达式:
以下是具体发生的步骤:
转换:
(int)$var['x']
首先进行评估,将字符串转换"5"
为整数5
。比较:
<
接下来评估运算符。由于优先<
级高于,因此计算??
表达式,得出结果。0 < 1
true
空合并:现在 PHP 计算
5 ?? true
。由于5
不null
,因此空合并运算符的结果为5
。条件检查:在
if
语句中,非零数字为真,因此条件计算为true
,并打印“小于 1”。在示例2中,也出现了类似的误解:
这解释为:
由于
$var['x']
是"5"
(非空值),因此空合并运算符返回"5"
。在 PHP 中,非空字符串(除"0"
)为真,因此条件为真,并打印“less”。在示例 3 中,您可以通过添加括号来强制执行预期的顺序。
$var['x']??0
这里,首先计算括号内的表达式。由于$var['x']
存在,因此返回"5"
,然后转换为5
。比较结果5 < 1
正确为false
,因此打印“大于 1”。出现意外行为的原因是,如果没有正确分组,PHP 会在应用空合并运算符之前评估强制类型转换和比较。添加显式括号可以明确操作顺序并确保表达式按预期进行评估。