有人能解释一下PHP中三元运算符简写(?:)和空合并运算符(??)之间的区别吗?

他们什么时候表现不同,什么时候表现相同(如果真的发生了的话)?

$a ?: $b

VS.

$a ?? $b

当前回答

It seems there are pros and cons to using either ?? or ?:. The pro to using ?: is that it evaluates false and null and "" the same. The con is that it reports an E_NOTICE if the preceding argument is null. With ?? the pro is that there is no E_NOTICE, but the con is that it does not evaluate false and null the same. In my experience, I have seen people begin using null and false interchangeably but then they eventually resort to modifying their code to be consistent with using either null or false, but not both. An alternative is to create a more elaborate ternary condition: (isset($something) or !$something) ? $something : $something_else.

下面是一个使用??同时使用null和false的运算符:

$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---

$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---

然而,通过详细说明三元操作符,我们可以使一个假字符串或空字符串""的行为就像它是null一样,而不抛出e_notice:

$false = null;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---

$false = false;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---

$false = "";
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: ---

$false = true;
$var = (isset($false) or !$false) ? $false : "true";
echo $var . "---<br>";//returns: 1---

就我个人而言,我认为如果PHP的未来版本包含另一个新的操作符::?这取代了上面的语法。即: // $var = $false:?“真正的”;该语法将相等地计算null, false和“”,而不会抛出E_NOTICE…

其他回答

Null Coalescing运算符只执行两个任务:它检查变量是否已设置,以及变量是否为空。看看下面的例子:

<?php
# case 1:
$greeting = 'Hola';
echo $greeting ?? 'Hi There'; # outputs: 'Hola'

# case 2:
$greeting = null;
echo $greeting ?? 'Hi There'; # outputs: 'Hi There'

# case 3:
unset($greeting);
echo $greeting ?? 'Hi There'; # outputs: 'Hi There'

上面的代码示例说明,Null Coalescing运算符以同样的方式处理一个不存在的变量和一个被设置为Null的变量。

空合并运算符是对三元运算符的改进。下面的代码片段比较了这两者:

<?php /* example: checking for the $_POST field that goes by the name of 'fullname'*/
# in ternary operator
echo "Welcome ", (isset($_POST['fullname']) && !is_null($_POST['fullname']) ? $_POST['fullname'] : 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.
# in null coalecing operator
echo "Welcome ", ($_POST['fullname'] ?? 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.

因此,两者之间的区别在于空合并操作符操作符被设计为比三元操作符更好地处理未定义变量。然而,三元操作符是if-else的简写。

Null Coalescing运算符并不意味着要取代三元运算符,但在一些用例中,比如上面的例子,它允许您以更少的麻烦编写干净的代码。

学分:http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples

:哦?-表示如果第一个操作数为真,则返回该操作数。否则,它将返回第二个。

?? -如果第一个操作数存在且不为空,则返回值。如果是,则返回;否则,它返回第二个操作数。

我发现一篇文章很好地描述了这种差异: https://www.fparedes.com/blog/null-coalescing-vs-elvis-operator-php/

当使用像$_GET或$_REQUEST这样的超全局变量时,你应该意识到它们可能是一个空字符串。 在这个特殊的例子中

$username = $_GET['user'] ?? 'nobody';

将失败,因为$username的值现在是一个空字符串。

所以当使用$_GET甚至$_REQUEST时,你应该像这样使用三元操作符:

$username = (!empty($_GET['user'])?$_GET['user']:'nobody';

现在$username的值是'nobody'。

向下滚动这个链接并查看该部分,它为您提供了如下所示的比较示例:

<?php
/** Fetches the value of $_GET['user'] and returns 'nobody' if it does not exist. **/
$username = $_GET['user'] ?? 'nobody';
/** This is equivalent to: **/
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

/** Coalescing can be chained: this will return the first defined value out of $_GET['user'], $_POST['user'], and 'nobody'. **/
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
?>

null合并运算符(??)已被添加为语法糖,用于需要将三元值与isset()结合使用的常见情况。如果操作数存在且不为NULL,则返回第一个操作数;否则返回第二个操作数。

本质上,使用合并操作符将使其自动检查null,不像三元操作符。

在php交互模式(php -a on terminal)上运行下面的代码。每行上的注释显示结果。

var_export (false ?? 'value2');   // false
var_export (true  ?? 'value2');   // true
var_export (null  ?? 'value2');   // value2
var_export (''    ?? 'value2');   // ""
var_export (0     ?? 'value2');   // 0

var_export (false ?: 'value2');   // value2
var_export (true  ?: 'value2');   // true
var_export (null  ?: 'value2');   // value2
var_export (''    ?: 'value2');   // value2
var_export (0     ?: 'value2');   // value2

空合并运算符??

?? 就像一个“门”,只让NULL通过。 它总是返回第一个参数,除非第一个参数恰好是NULL。 这意味着??与(!isset() || is_null())相同

使用??

Shorten !isset() || is_null()检查 例如$object = $object ??新objClassName ();

堆叠空合并运算符

        $v = $x ?? $y ?? $z; 

        // This is a sequence of "SET && NOT NULL"s:

        if( $x  &&  !is_null($x) ){ 
            return $x; 
        } else if( $y && !is_null($y) ){ 
            return $y; 
        } else { 
            return $z; 
        }

三元运算符?:

?:就像一个门,让任何虚假的东西通过-包括NULL 任何错误:0,空字符串,NULL, false, !isset(),空() 就像以前的三元运算符:X ?Y: z 注意:?:将在未定义(unset或!isset())变量上抛出PHP NOTICE

?的用法:

检查empty(), !isset(), is_null()等 缩短三元操作像!empty($x) ?$x: $y到$x ?: $y 缩短if(!$x) {echo $x;} else {echo $y;回显$x ?: $y

叠加三元运算符

        echo 0 ?: 1 ?: 2 ?: 3; //1
        echo 1 ?: 0 ?: 3 ?: 2; //1
        echo 2 ?: 1 ?: 0 ?: 3; //2
        echo 3 ?: 2 ?: 1 ?: 0; //3
    
        echo 0 ?: 1 ?: 2 ?: 3; //1
        echo 0 ?: 0 ?: 2 ?: 3; //2
        echo 0 ?: 0 ?: 0 ?: 3; //3

    
        // Source & Credit: http://php.net/manual/en/language.operators.comparison.php#95997
   
        // This is basically a sequence of:

 
        if( truthy ) {}
        else if(truthy ) {}
        else if(truthy ) {}
        ..
        else {}

将两者叠加,我们可以将其缩短为:

        if( isset($_GET['name']) && !is_null($_GET['name'])) {
            $name = $_GET['name'];
        } else if( !empty($user_name) ) {
             $name = $user_name; 
        } else {
            $name = 'anonymous';
        }

:

        $name = $_GET['name'] ?? $user_name ?: 'anonymous';

很酷,对吧?: -)