有人能解释一下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';
这是一个合适的聚结算子。
其他回答
其他的答案更深入,给出了很好的解释。对于那些寻求快速答案的人,
$a ?: 'fallback'是$a ?$a: 'fallback'
而
一美元? ?'回退'是$a = isset($a) ?$a: 'fallback'
主要的区别在于左操作符是:
一个非空的假值(0,",false,[],…) 未定义的变量
向下滚动这个链接并查看该部分,它为您提供了如下所示的比较示例:
<?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,不像三元操作符。
当你的第一个参数为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(而??不会)。
当使用像$_GET或$_REQUEST这样的超全局变量时,你应该意识到它们可能是一个空字符串。 在这个特殊的例子中
$username = $_GET['user'] ?? 'nobody';
将失败,因为$username的值现在是一个空字符串。
所以当使用$_GET甚至$_REQUEST时,你应该像这样使用三元操作符:
$username = (!empty($_GET['user'])?$_GET['user']:'nobody';
现在$username的值是'nobody'。