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

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

$a ?: $b

VS.

$a ?? $b

当前回答

对于初学者:

空合并运算符(??)

除了空值和未定义(变量/数组索引/对象属性)之外,所有内容都为真

ex:

$array = [];
$object = new stdClass();

var_export (false ?? 'second');                           # false
var_export (true  ?? 'second');                           # true
var_export (null  ?? 'second');                           # 'second'
var_export (''    ?? 'second');                           # ""
var_export ('some text'    ?? 'second');                  # "some text"
var_export (0     ?? 'second');                           # 0
var_export ($undefinedVarible ?? 'second');               # "second"
var_export ($array['undefined_index'] ?? 'second');       # "second"
var_export ($object->undefinedAttribute ?? 'second');     # "second"

这基本上是检查变量(数组索引,对象属性..Etc)是存在的,不是空的。类似于isset函数

三元运算符简写(?:)

每个假的东西(false,null,0,空字符串)都是假的,但如果它是一个未定义的,它也会是假的,但Notice会抛出

ex

$array = [];
$object = new stdClass();

var_export (false ?: 'second');                           # "second"
var_export (true  ?: 'second');                           # true
var_export (null  ?: 'second');                           # "second"
var_export (''    ?: 'second');                           # "second"
var_export ('some text'    ?? 'second');                  # "some text"
var_export (0     ?: 'second');                           # "second"
var_export ($undefinedVarible ?: 'second');               # "second" Notice: Undefined variable: ..
var_export ($array['undefined_index'] ?: 'second');       # "second" Notice: Undefined index: ..
var_export ($object->undefinedAttribute ?: 'second');     # "Notice: Undefined index: ..

希望这能有所帮助

其他回答

两者都是较长的表达式的简写。

:是$a ?$a: $b。如果$a的值为TRUE,则该表达式的值为$a。

?? 是isset($a)的缩写吗?$a: $b。如果设置了$a且不为空,则该表达式将计算为$a。

当$a未定义或为空时,它们的用例重叠。当$a没有定义时??不会产生E_NOTICE,但是结果是一样的。当$a为空时,结果是相同的。

如果你使用这样的快捷方式三元操作符,如果没有设置$_GET['username'],它会引起一个通知:

$val = $_GET['username'] ?: 'default';

所以你必须这样做:

$val = isset($_GET['username']) ? $_GET['username'] : 'default';

空合并操作符等价于上面的语句,如果$_GET['username']未设置或为空,将返回'default':

$val = $_GET['username'] ?? 'default';

注意,它不检查真实性。它只检查它是否已设置且不为空。

你也可以这样做,并且返回第一个定义的值(set而不是null):

$val = $input1 ?? $input2 ?? $input3 ?? 'default';

这是一个合适的聚结算子。

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

<?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,不像三元操作符。

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

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

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

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

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

现在$username的值是'nobody'。

class a
{
    public $a = 'aaa';
}

$a = new a();

echo $a->a;  // Writes 'aaa'
echo $a->b;  // Notice: Undefined property: a::$b

echo $a->a ?? '$a->a does not exists';  // Writes 'aaa'

// Does not throw an error although $a->b does not exist.
echo $a->b ?? '$a->b does not exist.';  // Writes $a->b does not exist.

// Does not throw an error although $a->b and also $a->b->c does not exist.
echo $a->b->c ?? '$a->b->c does not exist.';  // Writes $a->b->c does not exist.