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

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

$a ?: $b

VS.

$a ?? $b

当前回答

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

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

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

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

其他回答

当涉及到动态数据处理时,它们的行为都不同。

如果变量为空("),空合并将把变量视为真值,但速记三元操作符不会。这是需要记住的。

$a = NULL;
$c = '';

print $a ?? '1b';
print "\n";

print $a ?: '2b';
print "\n";

print $c ?? '1d';
print "\n";

print $c ?: '2d';
print "\n";

print $e ?? '1f';
print "\n";

print $e ?: '2f';

输出:

1b
2b

2d
1f

Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f

链接:https://3v4l.org/ZBAa1

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

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.

当你的第一个参数为null时,它们基本上是相同的,除了当你有一个未定义的变量时,null合并不会输出一个E_NOTICE。PHP 7.0迁移文档是这样说的:

空合并运算符(??)已被添加为语法糖 对于一般情况下需要使用三元组合的 收取()。如果操作数存在且不为NULL,则返回第一个操作数; 否则返回第二个操作数。

下面是一些示例代码来演示这一点:

<?php

$a = null;

print $a ?? 'b'; // b
print "\n";

print $a ?: 'b'; // b
print "\n";

print $c ?? 'a'; // a
print "\n";

print $c ?: 'a'; // Notice: Undefined variable: c in /in/apAIb on line 14
print "\n";

$b = array('a' => null);

print $b['a'] ?? 'd'; // d
print "\n";

print $b['a'] ?: 'd'; // d
print "\n";

print $b['c'] ?? 'e'; // e
print "\n";

print $b['c'] ?: 'e'; // Notice: Undefined index: c in /in/apAIb on line 33
print "\n";

有提示的那几行是我使用的简略三元运算符而不是空合并运算符。但是,即使有通知,PHP也会返回相同的响应。

执行代码:https://3v4l.org/McavC

当然,这总是假设第一个参数为空。一旦它不再为空,你就会得到??运算符总是返回第一个参数,而?:简写只在第一个参数为真时才返回,这取决于PHP如何将东西类型转换为布尔值。

So:

$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'

那么$a等于false, $b等于g。

实用的简短回答:

Try:

var_dump('' ?: 'ok');

vs

var_dump('' ?? 'ok');

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

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


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