bal*_*ing 285 php ternary-operator null-coalescing-operator php-7
有人可以解释PHP中三元运算符速记(?:)和空合并运算符(??)之间的差异吗?
他们什么时候表现不同,以同样的方式(如果这种情况发生)?
$a ?: $b
Run Code Online (Sandbox Code Playgroud)
VS.
$a ?? $b
Run Code Online (Sandbox Code Playgroud)
Mas*_*din 287
当你的第一个参数为null时,它们基本相同,只是E_NOTICE当你有一个未定义的变量时,null合并将不会输出.在PHP 7.0迁移的文档有这样一段话:
对于需要将三元组与isset()结合使用的常见情况,已添加空合并运算符(??)作为语法糖.它返回第一个操作数(如果存在且不为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";
Run Code Online (Sandbox Code Playgroud)
它的输出:
$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'
Run Code Online (Sandbox Code Playgroud)
有通知的行是我使用简写三元运算符而不是空合并运算符的行.但是,即使有通知,PHP也会给出相同的响应.
执行代码:https://3v4l.org/McavC
当然,这总是假设第一个参数是null.一旦它不再为null,那么你最终会产生差异,因为??操作符总是返回第一个参数,而?:速记只有在第一个参数是真的时才会发生,并且这依赖于PHP如何将事物类型转换为布尔值.
所以:
<?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";
Run Code Online (Sandbox Code Playgroud)
然后$a将等于false和$b等于'g'.
And*_*rew 67
如果您使用这样的快捷方式三元运算符,如果$_GET['username']未设置则会引发通知:
$val = $_GET['username'] ?: 'default';
Run Code Online (Sandbox Code Playgroud)
所以你必须做这样的事情:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
Run Code Online (Sandbox Code Playgroud)
该空合并运算符是等同于上面的语句,将返回"默认"如果$_GET['username']没有设置或者是null:
$val = $_GET['username'] ?? 'default';
Run Code Online (Sandbox Code Playgroud)
请注意,它不会检查真实性.它仅检查是否已设置且不为空.
您也可以这样做,并返回第一个定义的(set和not null)值:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
Run Code Online (Sandbox Code Playgroud)
现在这是一个合适的合并运算符.
a20*_*a20 43
在php交互模式下(php -a在终端上)进行下面的操作.每行的注释显示结果.
var_dump (false ?? 'value2'); # bool(false)
var_dump (true ?? 'value2'); # bool(true)
var_dump (null ?? 'value2'); # string(6) "value2"
var_dump ('' ?? 'value2'); # string(0) ""
var_dump (0 ?? 'value2'); # int(0)
var_dump (false ?: 'value2'); # string(6) "value2"
var_dump (true ?: 'value2'); # bool(true)
var_dump (null ?: 'value2'); # string(6) "value2"
var_dump ('' ?: 'value2'); # string(6) "value2"
var_dump (0 ?: 'value2'); # string(6) "value2"
Run Code Online (Sandbox Code Playgroud)
??:??就像一个只允许NULL通过的"门".NULL. ??和( !isset() || is_null() )?:?:就像一扇anything falsy通过的大门- 包括NULL0,empty string,NULL,false,!isset(),empty()...任何气味falsyecho ($x ? $x : false) ?:将抛出PHP NOTICE未定义(unset或!isset())变量??和?:..?:时
empty($x)检查!empty($x) ? $x : $y可以缩短为$x ?: $y if(!$x) { fn($x); } else { fn($y); } 可以缩短为 fn(($x ?: $y)) ??时
!isset() || is_null()检查$object = $object ?? new objClassName();三元运算符可堆叠 ...
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
Run Code Online (Sandbox Code Playgroud)
这基本上是一系列:
if( truthy ) {}
else if(truthy ) {}
else if(truthy ) {}
..
else {}
Run Code Online (Sandbox Code Playgroud)Null Coalese操作员可堆叠 ...
$v = $x ?? $y ?? $z;
Run Code Online (Sandbox Code Playgroud)
这是一系列:
if(!isset($x) || is_null($x) ) {}
else if(!isset($y) || is_null($y) ) {}
else {}
Run Code Online (Sandbox Code Playgroud)使用堆叠,我可以缩短这个:
if(!isset($_GET['name'])){
if(isset($user_name) && !empty($user_name)){
$name = $user_name;
}else {
$name = 'anonymous';
}
} else {
$name = $_GET['name'];
}
Run Code Online (Sandbox Code Playgroud)
对此:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
Run Code Online (Sandbox Code Playgroud)
很酷,对吗?:-)
Dha*_*era 42
主要区别在于
三元运算表达式 expr1 ?: expr3返回expr1如果expr1计算结果为
TRUE,但是,从另一方面空合并运算符表达式 (expr1) ?? (expr2)
的计算结果为expr1,如果expr1是不 NULL
expr1 ?: expr3如果左侧值(expr1) 不存在但是另一方面Null Coalescing Operator Null Coalescing Operator (expr1) ?? (expr2),则三元运算符会发出通知.如果左侧值不存在,则不发出通知(expr1) ,就像isset().
TernaryOperator是左关联的
((true ? 'true' : false) ? 't' : 'f');
Run Code Online (Sandbox Code Playgroud)
Null Coalescing Operator是右关联的
($a ?? ($b ?? $c));
Run Code Online (Sandbox Code Playgroud)现在让我们解释一下示例之间的区别:
三元运算符 (?:)
$x='';
$value=($x)?:'default';
var_dump($value);
// The above is identical to this if/else statement
if($x){
$value=$x;
}
else{
$value='default';
}
var_dump($value);
Run Code Online (Sandbox Code Playgroud)
空融合运算符 (??)
$value=($x)??'default';
var_dump($value);
// The above is identical to this if/else statement
if(isset($x)){
$value=$x;
}
else{
$value='default';
}
var_dump($value);
Run Code Online (Sandbox Code Playgroud)
下面是解释之间的差异性和相似性表'??'和?:
特别注意:null合并运算符和三元运算符是一个表达式,它不会计算变量,而是表达式的结果.知道是否要通过引用返回变量很重要.声明返回$ foo ?? $酒吧; 并返回$ var == 42?$ a:$ b; 因此,在按引用返回功能中将不起作用并发出警告.
Cha*_*haz 14
在动态数据处理方面,它们的行为都不同.
如果变量为空(''),则空合并将把变量视为true,但速记三元运算符则不会.这是需要考虑的事情.
$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';
Run Code Online (Sandbox Code Playgroud)
并输出:
1b
2b
2d
1f
Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f
Run Code Online (Sandbox Code Playgroud)
St3*_*3an 10
实用简答:
尝试:
var_dump('' ?: 'ok'); // prints: ok
Run Code Online (Sandbox Code Playgroud)
与
var_dump('' ?? 'ok'); // prints empty string
Run Code Online (Sandbox Code Playgroud)
?:如果左侧值的计算结果为“真实”,则速记三元运算符 ( ) 将返回左侧的值;否则将返回右侧值。
然而
??如果左侧值已声明且不为空,则空合并运算符 ( ) 将返回左侧的值;否则将返回右侧值。
换句话说,?:测试真实性,并??充当 的简写isset()。
*警告:如果你想用 测试一个变量,?:你必须首先确保它被初始化/设置,否则 PHP 将引发一个E_NOTICE(反之则??不会)。
两者都是较长表达的缩写.
?:是的缩写$a ? $a : $b.如果$ a的计算结果为TRUE,则此表达式将计算为$ a .
??是的缩写isset($a) ? $a : $b.如果设置了$ a,则此表达式将计算为$ a,而不是null.
当$ a未定义或为null时,它们的用例重叠.当$ a未定义??时,不会产生E_NOTICE,但结果是相同的.当$ a为null时,结果是相同的.
向下滚动此链接并查看该部分,它为您提供了一个比较示例,如下所示:
<?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';
?>
Run Code Online (Sandbox Code Playgroud)
但是,不建议将运算符链接起来,因为它会使以后阅读代码时更难理解。
空合并运算符 (??) 已被添加为语法糖,用于需要将三元与 isset() 结合使用的常见情况。如果存在且不为 NULL,则返回其第一个操作数;否则它返回它的第二个操作数。
本质上,与三元运算符不同,使用合并运算符将使其自动检查 null。
对于初学者:
空合并运算符(??)
除null值和未定义(变量/数组索引/对象属性)外,其他所有内容均为真
例如:
$array = [];
$object = new stdClass();
var_export (false ?? 'second'); # false
var_export (true ?? 'second'); # true
var_export (null ?? 'second'); # 'second'
var_export ('' ?? 'second'); # ""
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?? 'second'); # 0
var_export ($undefinedVarible ?? 'second'); # "second"
var_export ($array['undefined_index'] ?? 'second'); # "second"
var_export ($object->undefinedAttribute ?? 'second'); # "second"
Run Code Online (Sandbox Code Playgroud)
这基本上是检查变量(数组索引,对象属性等)是否存在null。类似于isset功能
三元运算符速记(?:)
每一个虚假的东西(false,null,0,空字符串)都是来作为假的,但如果它是一个不确定的,也都为假,但Notice会抛出
前
$array = [];
$object = new stdClass();
var_export (false ?: 'second'); # "second"
var_export (true ?: 'second'); # true
var_export (null ?: 'second'); # "second"
var_export ('' ?: 'second'); # "second"
var_export ('some text' ?? 'second'); # "some text"
var_export (0 ?: 'second'); # "second"
var_export ($undefinedVarible ?: 'second'); # "second" Notice: Undefined variable: ..
var_export ($array['undefined_index'] ?: 'second'); # "second" Notice: Undefined index: ..
var_export ($object->undefinedAttribute ?: 'second'); # "Notice: Undefined index: ..
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助