PHP中的null合并与三元运算符(再次)

huangapple go评论64阅读模式
英文:

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'] 的值不是 nullfalse,则结果操作将是:

$_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.

huangapple
  • 本文由 发表于 2023年6月16日 09:22:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76486421.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定