PHP短三元运算符(“Elvis”)和空合并运算符的比较

559

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

它们在什么情况下会表现出不同的行为,在什么情况下又是相同的(如果有的话)?

$a ?: $b

对比。

$a ?? $b

3
一个好的测试方法是使用交互模式下的php控制台(php -a)。然后设置ini_set('error_reporting', 'E_ALL')ini_set('display_errors', 'on')。接着你可以尝试var_dump($var ?? 'default')),看看在此之前设置任何类型的值会发生什么。 - St3an
很难通过谷歌搜索找到:文档可以省略三元运算符的中间部分。表达式expr1 ?: expr3如果expr1为真,则返回expr1,否则返回expr3 - Basj
15个回答

1
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.

如果您在链中有一些方法调用,PHP具有nullsafe运算符:PHP中是否有“nullsafe运算符”? - mickmackusa

1
似乎使用???:都有其利弊。使用?:的好处是它将false、null和""视为相同,但缺点是如果前面的参数为null,则会报告E_NOTICE。使用??的好处是没有E_NOTICE,但缺点是它不将false和null视为相同。根据我的经验,我发现人们开始将null和false互换使用,但最终会修改代码以使用null或false中的一个,而不是两者兼用。另一种选择是创建更复杂的三元条件:(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 :? "true"; 这种语法将平等地评估null、false和“”而不会抛出E_NOTICE...

4
你可以使用 $var = $false ?? null ?: "字符串为空/假值/null/未定义"; - RedSparr0w
哇... ?? null ?: 这个东西真的很棒,谢谢你聪明的先生。 - Blaine Lafreniere

0

当使用超全局变量,如 $_GET 或 $_REQUEST 时,您应该意识到它们可能是空字符串。在这种特殊情况下,例如:

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

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

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

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

现在$username的值如预期一样是'nobody'。


好的发现。此外,在空字符串的情况下,合并运算符也会失败。 - Choxx

0

Null Coalescing operator 只执行两个任务:检查 变量是否已设置是否为空。请看以下示例:

<?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 operator”将不存在的变量和设置为“NULL”的变量视为同一种情况。
“Null Coalescing operator”是对“ternary operator”的改进。请看下面的代码片段比较这两者:
<?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.

所以,两者之间的区别在于Null Coalescing operator运算符比ternary operator更适合处理未定义的变量。而ternary operatorif-else的简写。 Null Coalescing operator并不意味着要取代ternary operator,但在某些用例中,例如上面的示例,它允许您编写更简洁的代码,减少麻烦。
致谢:http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples

isset($_POST['fullname']) 已经检查了 NULL 值 - 所以第一个例子中的 && !is_null($_POST['fullname']) 是多余的。 - Yaron U.

-2

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

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

我找到了一篇文章,非常好地描述了它们之间的区别: https://www.fparedes.com/blog/null-coalescing-vs-elvis-operator-php/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接