有人可以解释PHP中三元运算符速记(?:
)和空合并运算符(??
)之间的差异吗?
他们什么时候表现不同,以同样的方式(如果这种情况发生)?
$a ?: $b
VS.
$a ?? $b
MasterOdin.. 287
当你的第一个参数为null时,它们基本相同,只是E_NOTICE
当你有一个未定义的变量时,null合并将不会输出.在PHP 7.0迁移的文档有这样一段话:
对于需要将三元组与isset()结合使用的常见情况,已添加空合并运算符(??)作为语法糖.它返回第一个操作数(如果存在且不为NULL); 否则返回第二个操作数.
这是一些示例代码来演示:
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";
它的输出:
$a = false ?? 'f'; // false $b = false ?: 'g'; // 'g'
有通知的行是我使用简写三元运算符而不是空合并运算符的行.但是,即使有通知,PHP也会给出相同的响应.
执行代码:https://3v4l.org/McavC
当然,这总是假设第一个参数是null
.一旦它不再为null,那么你最终会产生差异,因为??
操作符总是返回第一个参数,而?:
速记只有在第一个参数是真的时才会发生,并且这依赖于PHP如何将事物类型转换为布尔值.
所以:
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";
然后$a
将等于false
和$b
等于'g'
.
当你的第一个参数为null时,它们基本相同,只是E_NOTICE
当你有一个未定义的变量时,null合并将不会输出.在PHP 7.0迁移的文档有这样一段话:
对于需要将三元组与isset()结合使用的常见情况,已添加空合并运算符(??)作为语法糖.它返回第一个操作数(如果存在且不为NULL); 否则返回第二个操作数.
这是一些示例代码来演示:
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";
它的输出:
$a = false ?? 'f'; // false $b = false ?: 'g'; // 'g'
有通知的行是我使用简写三元运算符而不是空合并运算符的行.但是,即使有通知,PHP也会给出相同的响应.
执行代码:https://3v4l.org/McavC
当然,这总是假设第一个参数是null
.一旦它不再为null,那么你最终会产生差异,因为??
操作符总是返回第一个参数,而?:
速记只有在第一个参数是真的时才会发生,并且这依赖于PHP如何将事物类型转换为布尔值.
所以:
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";
然后$a
将等于false
和$b
等于'g'
.
如果您使用这样的快捷方式三元运算符,如果$_GET['username']
未设置则会引发通知:
$val = $_GET['username'] ?: 'default';
所以你必须做这样的事情:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
该空合并运算符是等同于上面的语句,将返回"默认"如果$_GET['username']
没有设置或者是null
:
$val = $_GET['username'] ?? 'default';
请注意,它不会检查真实性.它仅检查是否已设置且不为空.
您也可以这样做,并返回第一个定义的(set和not null
)值:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
现在这是一个合适的合并运算符.
在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"所以这是我的解释:
??
:
??
就像一个只允许NULL通过的"门".
因此,它始终返回第一个参数,除非第一个参数恰好是NULL
.
这意味着??
和( !isset() || is_null() )
?:
?:
就像一扇anything falsy
通过的大门- 包括NULL
0
,empty string
,NULL
,false
,!isset()
,empty()
...任何气味falsy
就像经典的三元运算符一样: echo ($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
此代码的来源和信誉
这基本上是一系列:
if( truthy ) {} else if(truthy ) {} else if(truthy ) {} .. else {}
Null Coalese操作员可堆叠 ...
$v = $x ?? $y ?? $z;
这是一系列:
if(!isset($x) || is_null($x) ) {} else if(!isset($y) || is_null($y) ) {} else {}
使用堆叠,我可以缩短这个:
if(!isset($_GET['name'])){ if(isset($user_name) && !empty($user_name)){ $name = $user_name; }else { $name = 'anonymous'; } } else { $name = $_GET['name']; }
对此:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
很酷,对吗?:-)
主要区别在于
三元运算表达式 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');
Null Coalescing Operator是右关联的
($a ?? ($b ?? $c));
现在让我们解释一下示例之间的区别:
三元运算符 (?:)
$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);
空融合运算符 (??)
$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);
下面是解释之间的差异性和相似性表'??'
和?:
特别注意:null合并运算符和三元运算符是一个表达式,它不会计算变量,而是表达式的结果.知道是否要通过引用返回变量很重要.声明返回$ foo ?? $酒吧; 并返回$ var == 42?$ a:$ b; 因此,在按引用返回功能中将不起作用并发出警告.
在动态数据处理方面,它们的行为都不同.
如果变量为空(''),则空合并将把变量视为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';
并输出:
1b 2b 2d 1f Notice: Undefined variable: e in /in/ZBAa1 on line 21 2f
链接:https://3v4l.org/ZBAa1
两者都是较长表达的缩写.
?:
是的缩写$a ? $a : $b
.如果$ a的计算结果为TRUE,则此表达式将计算为$ a .
??
是的缩写isset($a) ? $a : $b
.如果设置了$ a,则此表达式将计算为$ a,而不是null.
当$ a未定义或为null时,它们的用例重叠.当$ a未定义??
时,不会产生E_NOTICE,但结果是相同的.当$ a为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"
这基本上是检查变量(数组索引,对象属性等)是否存在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: ..
希望这可以帮助