有人能解释一下PHP中三元运算符简写(?:)和空合并运算符(??)之间的区别吗?
他们什么时候表现不同,什么时候表现相同(如果真的发生了的话)?
$a ?: $b
VS.
$a ?? $b
有人能解释一下PHP中三元运算符简写(?:)和空合并运算符(??)之间的区别吗?
他们什么时候表现不同,什么时候表现相同(如果真的发生了的话)?
$a ?: $b
VS.
$a ?? $b
当前回答
如果你使用这样的快捷方式三元操作符,如果没有设置$_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';
这是一个合适的聚结算子。
其他回答
当你的第一个参数为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。
在php交互模式(php -a on terminal)上运行下面的代码。每行上的注释显示结果。
var_export (false ?? 'value2'); // false
var_export (true ?? 'value2'); // true
var_export (null ?? 'value2'); // value2
var_export ('' ?? 'value2'); // ""
var_export (0 ?? 'value2'); // 0
var_export (false ?: 'value2'); // value2
var_export (true ?: 'value2'); // true
var_export (null ?: 'value2'); // value2
var_export ('' ?: 'value2'); // value2
var_export (0 ?: 'value2'); // value2
空合并运算符??
?? 就像一个“门”,只让NULL通过。 它总是返回第一个参数,除非第一个参数恰好是NULL。 这意味着??与(!isset() || is_null())相同
使用??
Shorten !isset() || is_null()检查 例如$object = $object ??新objClassName ();
堆叠空合并运算符
$v = $x ?? $y ?? $z;
// This is a sequence of "SET && NOT NULL"s:
if( $x && !is_null($x) ){
return $x;
} else if( $y && !is_null($y) ){
return $y;
} else {
return $z;
}
三元运算符?:
?:就像一个门,让任何虚假的东西通过-包括NULL 任何错误:0,空字符串,NULL, false, !isset(),空() 就像以前的三元运算符:X ?Y: z 注意:?:将在未定义(unset或!isset())变量上抛出PHP NOTICE
?的用法:
检查empty(), !isset(), is_null()等 缩短三元操作像!empty($x) ?$x: $y到$x ?: $y 缩短if(!$x) {echo $x;} else {echo $y;回显$x ?: $y
叠加三元运算符
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 1 ?: 0 ?: 3 ?: 2; //1
echo 2 ?: 1 ?: 0 ?: 3; //2
echo 3 ?: 2 ?: 1 ?: 0; //3
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 0 ?: 0 ?: 2 ?: 3; //2
echo 0 ?: 0 ?: 0 ?: 3; //3
// Source & Credit: http://php.net/manual/en/language.operators.comparison.php#95997
// This is basically a sequence of:
if( truthy ) {}
else if(truthy ) {}
else if(truthy ) {}
..
else {}
将两者叠加,我们可以将其缩短为:
if( isset($_GET['name']) && !is_null($_GET['name'])) {
$name = $_GET['name'];
} else if( !empty($user_name) ) {
$name = $user_name;
} else {
$name = 'anonymous';
}
:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
很酷,对吧?: -)
:哦?-表示如果第一个操作数为真,则返回该操作数。否则,它将返回第二个。
?? -如果第一个操作数存在且不为空,则返回值。如果是,则返回;否则,它返回第二个操作数。
我发现一篇文章很好地描述了这种差异: https://www.fparedes.com/blog/null-coalescing-vs-elvis-operator-php/
实用的简短回答:
Try:
var_dump('' ?: 'ok');
vs
var_dump('' ?? 'ok');
如果测试值(或变量*)为false,第一个将返回“ok”
而
如果测试值(或变量*)为空或未初始化/设置,第二个将返回'ok'。
*警告:如果你想用?:测试一个变量,你必须首先确保它是初始化/设置的,否则PHP将引发一个E_NOTICE(而??不会)。
如果你使用这样的快捷方式三元操作符,如果没有设置$_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';
这是一个合适的聚结算子。