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

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

$a ?: $b

VS.

$a ?? $b

当前回答

实用的简短回答:

Try:

var_dump('' ?: 'ok');

vs

var_dump('' ?? 'ok');

如果测试值(或变量*)为false,第一个将返回“ok”

如果测试值(或变量*)为空或未初始化/设置,第二个将返回'ok'。


*警告:如果你想用?:测试一个变量,你必须首先确保它是初始化/设置的,否则PHP将引发一个E_NOTICE(而??不会)。

其他回答

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

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

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

其他的答案更深入,给出了很好的解释。对于那些寻求快速答案的人,

$a ?: 'fallback'是$a ?$a: 'fallback'

一美元? ?'回退'是$a = isset($a) ?$a: 'fallback'


主要的区别在于左操作符是:

一个非空的假值(0,",false,[],…) 未定义的变量

实用的简短回答:

Try:

var_dump('' ?: 'ok');

vs

var_dump('' ?? 'ok');

如果测试值(或变量*)为false,第一个将返回“ok”

如果测试值(或变量*)为空或未初始化/设置,第二个将返回'ok'。


*警告:如果你想用?:测试一个变量,你必须首先确保它是初始化/设置的,否则PHP将引发一个E_NOTICE(而??不会)。

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.

如果你使用这样的快捷方式三元操作符,如果没有设置$_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';

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