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

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

$a ?: $b

VS.

$a ?? $b

当前回答

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

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

$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

其他回答

当使用像$_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.

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

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

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