PHP 三元运算符没有按预期工作?

PHP Ternary Operators don't work as expected?

我有一个方法可以检查 param 是否为 null,但是如果我使用三元运算符来确保 false 结果不是字符串,我不会得到相同的预期结果...我白天是一名全栈 .NET 开发人员,但做一些 PHP 自由职业者,这让我很困惑......

$param = null;

// $active evaluates to true
$active = is_null($param) ? true : false;

// $active evaluates to false
$active = is_null($param) ? true : is_string($param)
    ? (strtolower($param) === 'true')
    : true;

我在C#中使用过嵌套的三元运算符JavaScript感觉好像无数次,但我不知道我是否尝试过PHP... PHP 尝试在表达结果之前评估所有嵌套的三元运算,或者我在这里遗漏了什么,因为根据我对这种情况的理解,三元运算符应该在两种情况下短路并评估为真。

您需要用括号 (),

括起您的第二个三元条件
<?php
$param = null;
// $active evaluates to true
$active = is_null($param) ? true : false;
echo "Simple ternary result = $active".PHP_EOL;
// $active evaluates to true
$active = is_null($param) ? true : (is_string($param)? (strtolower($param) === 'true'): true);
echo "Nested ternary result = $active";
?>

注:

It is recommended that you avoid "stacking" ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious:

参见 http://php.net/manual/en/language.operators.comparison.php

中的示例 #4

示例 #4 不明显的三元行为

<?php
// on first glance, the following appears to output 'true'
echo (true?'true':false?'t':'f');

// however, the actual output of the above is 't'
// this is because ternary expressions are evaluated from left to right

// the following is a more obvious version of the same code as above
echo ((true ? 'true' : false) ? 't' : 'f');

// here, you can see that the first expression is evaluated to 'true', which
// in turn evaluates to (bool)true, thus returning the true branch of the
// second ternary expression.
?>

演示: https://3v4l.org/gW8pk

这是 PHP 的一个众所周知的问题。我怀疑它永远不会被修复。使用括号或 if..elseswitch 语句来获得您想要的行为。

(在技术术语中,PHP 中的三元运算符是 "left associative",而在所有其他语言中使用此运算符的三元运算符是 "right associative"。后者是更符合逻辑的行为这个运算符。)

ternary operator 与大多数其他语言(如 C#)不同,它是左关联的。代码:

$active = is_null($param)
    ? true
    : is_string($param)
        ? (strtolower($param) === 'true')
        : true;

评价如下:

$active = ((is_null($param) ? true : is_string($param))
                                                        ? (strtolower($param) === 'true') : true);

您必须明确添加括号以确保 ?: 以熟悉的语言的方式工作:

$active = is_null($param)
    ? true
    : (is_string($param)
        ? (strtolower($param) === 'true')
        : true);