有人能解释一下PHP中三元运算符简写(?:)和空合并运算符(??)之间的区别吗?
他们什么时候表现不同,什么时候表现相同(如果真的发生了的话)?
$a ?: $b
VS.
$a ?? $b
有人能解释一下PHP中三元运算符简写(?:)和空合并运算符(??)之间的区别吗?
他们什么时候表现不同,什么时候表现相同(如果真的发生了的话)?
$a ?: $b
VS.
$a ?? $b
当前回答
两者都是较长的表达式的简写。
:是$a ?$a: $b。如果$a的值为TRUE,则该表达式的值为$a。
?? 是isset($a)的缩写吗?$a: $b。如果设置了$a且不为空,则该表达式将计算为$a。
当$a未定义或为空时,它们的用例重叠。当$a没有定义时??不会产生E_NOTICE,但是结果是一样的。当$a为空时,结果是相同的。
其他回答
实用的简短回答:
Try:
var_dump('' ?: 'ok');
vs
var_dump('' ?? 'ok');
如果测试值(或变量*)为false,第一个将返回“ok”
而
如果测试值(或变量*)为空或未初始化/设置,第二个将返回'ok'。
*警告:如果你想用?:测试一个变量,你必须首先确保它是初始化/设置的,否则PHP将引发一个E_NOTICE(而??不会)。
向下滚动这个链接并查看该部分,它为您提供了如下所示的比较示例:
<?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,不像三元操作符。
两者都是较长的表达式的简写。
:是$a ?$a: $b。如果$a的值为TRUE,则该表达式的值为$a。
?? 是isset($a)的缩写吗?$a: $b。如果设置了$a且不为空,则该表达式将计算为$a。
当$a未定义或为空时,它们的用例重叠。当$a没有定义时??不会产生E_NOTICE,但是结果是一样的。当$a为空时,结果是相同的。
当你的第一个参数为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。
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…