英文:
PHP null coalescing with ternary operator (again)
问题
以下是翻译好的部分:
当 $_SERVER['MODE']
未设置 时,以下代码可以理解地返回 "dev":
$_SERVER['MODE'] ?? null === 'production' ? 'prod' : 'dev'
这是因为 $_SERVER['MODE'] ?? null
解析为 NULL
,显然与 "production" 不严格相等,因此三元表达式的 右 操作数会占上风。
然而,如果我将 $_SERVER['MODE']
设置为任何真值,情况就变得奇怪了。代码会返回 "prod"!
我不明白为什么。当 $_SERVER['MODE']
被设置时,空合并运算符会解析为它设置的任何值。所以,除非它被设置为 "production",否则三元表达式的 右 操作数应该仍然占上风。为什么不是呢?
此外,如果我添加括号,就像这样:
($_SERVER['MODE'] ?? null) === 'production' ? 'prod' : 'dev'
然后它就按预期运行了。但是为什么没有括号就不行呢?
相关但不重复的问题:https://stackoverflow.com/questions/46514718/php-null-coalesce-ternary-operators-strange-behavior
附言:这个困惑刚刚让我花费了$40。$_SERVER['MODE']
被设置为 "dev",但由于表达式解析为 "prod",真实的AWS实例被启动了 :D。
英文:
The following code understandably yields "dev" when $_SERVER['MODE']
is not set:
$_SERVER['MODE'] ?? null === 'production' ? 'prod' : 'dev'
That is because $_SERVER['MODE'] ?? null
resolves to NULL
which, of course, is not strictly equal to "production", so the right operand of the ternary expression prevails.
However, if I set $_SERVER['MODE']
to just any truthy value, things become strange. The code yields "prod"!
I do not understand why. When $_SERVER['MODE']
is set, the null coalescing resolves to whatever value it is set to. So, unless it is set to "production", the right operand of the ternary expression should still prevail. Why does it not?
Besides, if I add brackets like this:
($_SERVER['MODE'] ?? null) === 'production' ? 'prod' : 'dev'
— then it works as expected. But why not without the brackets?
Related but not dupe: https://stackoverflow.com/questions/46514718/php-null-coalesce-ternary-operators-strange-behavior
P.S. This confusion just costed me $40. $_SERVER['MODE']
was set to "dev" but, as the expression resolved to "prod", real AWS instances were started :D.
答案1
得分: 2
$_SERVER['MODE'] ?? null === 'production'
可以很容易地进行测试,方法是将其隔离开来。
var_dump(1 ?? null === 'production'); // 1
var_dump(null ?? null === 'production'); // false
var_dump(null ?? 'production' === 'production'); // true
这意味着,除非你添加括号,否则你的操作数会像这样分组:
( $_SERVER['MODE'] ?? (null === 'production') ) ? 'prod' : 'dev'
如果 $_SERVER['MODE']
的值不是 null
或 false
,则结果操作将是:
$_SERVER['MODE'] ? 'prod' : 'dev'
因此,任何真值都将评估为 'prod'。
这是因为 null 合并运算符的优先级比三元运算符高(可以在这里看到)。
希望这有意义。
作为建议,尝试在这种情况下始终添加括号。这样代码更容易阅读、维护和调试。这样就不会因为这种问题而让人发疯或损失金钱。
英文:
You can test the result of $_SERVER['MODE'] ?? null === 'production'
pretty easily by isolating it.
var_dump(1 ?? null === 'production'); // 1
var_dump(null ?? null === 'production'); // false
var_dump(null ?? 'production' === 'production'); // true
That means, your operands are grouped like this unless you add the brackets:
( $_SERVER['MODE'] ?? (null === 'production') ) ? 'prod' : 'dev'
If $_SERVER['MODE']
is any other value than null
or false
, the resulting operation will be:
$_SERVER['MODE'] ? 'prod' : 'dev'
So, every truthy value will evaluate to 'prod'.
This is because the nullish coalesching operator has a higher precedence order than the ternary operator ( as can be seen here )
I hope that makes sense.
As a piece of advice, try to always add brackets in cases like this. The code is easier to read, maintain, and debug. And no one will go insane or lose money over issues like this one.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论