为什么我的 IF ($a || $b && $c) 语句没有按预期工作(PHP 运算符优先级)

Why doesn't my IF ($a || $b && $c) statement work as expected (PHP operator precedence)

多年来,我注意到有很多 PHP 程序员不理解确保始终包含括号的重要性,即使是 "not needed."(提示: 总是需要)

示例场景:

您的任务是更新登录页面以允许使用他们现有的密码或带有用户名的登录令牌。

现有代码如下所示:

if ($password_is_valid && $username_is_valid) {
    // Success
} else {
    // Failure
}

您将代码更新为如下所示:

if ($password_is_valid || $token_is_valid && $username_is_valid) {
    // Success
} else {
    // Failure
}

经过几次测试以确保用户仍然可以登录后,您确认一切正常并收工。快进几个星期或几个月,你的经理对你大喊大叫,想知道其中一名销售人员如何能够以管理员身份登录并在不知道管理员密码的情况下给自己加薪。

阅读所有登录代码 3 遍后,您完全不知道这是怎么发生的。最后你求助于一些手动测试,最终你发现任何人的正确密码都可以与其他人的用户名一起使用,只要该用户名确实存在于数据库中。

这怎么可能?


请注意: 此 post 纯粹是为了帮助 newer/less-seasoned 开发人员解决基于对 &&||一起努力。我确实试图在 S.O 上找到类似的 post。但是我找不到,或者至少 PHP.

找不到

简短的回答是你误解了how operator precedence works in PHP。但是,这个解释太详细了,超出了这个问题的范围。

最简单和最好的答案是确保在混合运算符时始终使用括号 AND/OR 当不清楚应该首先评估什么时。

在我们的示例场景中,更新后的代码应该如下所示:

if (($password_is_valid || $token_is_valid) && $username_is_valid) {
    // Success
} else {
    // Failure
}

但是,由于更新后的代码 没有括号来指定 运行 操作的顺序 PHP 对其进行了解释像这样:

if ($password_is_valid || ($token_is_valid && $username_is_valid)) {
    // Success
} else {
    // Failure
}

如果您仍然感到困惑,这是一个代码示例,您可以使用它来更好地理解这个问题:https://3v4l.org/SmIip

此外,即使括号"really aren't needed to function as desired"也会让你的代码更易读,更容易理解。这对于下一个将阅读您的代码的开发人员来说很重要。 (实际上可能是你在 6 个月以上时忘记了你在写它时的想法。)所以总是添加它们,即使你确定它们 "aren't needed."