PHP 三元运算符与空合并运算符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34571330/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP ternary operator vs null coalescing operator
提问by balping
Can someone explain the differences between ternary operator shorthand (?:
) and null coalescing operator (??
) in PHP?
有人能解释一下PHP 中三元运算符简写 ( ?:
) 和空合并运算符 ( ??
)之间的区别吗?
When do they behave differently and when in the same way (if that even happens)?
他们什么时候表现不同,什么时候表现相同(如果发生的话)?
$a ?: $b
VS.
对比。
$a ?? $b
回答by MasterOdin
When your first argument is null, they're basically the same except that the null coalescing won't output an E_NOTICE
when you have an undefined variable. The PHP 7.0 migration docshas this to say:
当您的第一个参数为 null 时,它们基本相同,只是E_NOTICE
当您有未定义的变量时,null 合并不会输出 an 。在PHP 7.0迁移的文档有这样一段话:
The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.
空合并运算符 (??) 已被添加为语法糖,用于需要将三元与 isset() 结合使用的常见情况。如果存在且不为 NULL,则返回其第一个操作数;否则它返回它的第二个操作数。
Here's some example code to demonstrate this:
下面是一些示例代码来演示这一点:
<?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";
The lines that have the notice are the ones where I'm using the shorthand ternary operator as opposed to the null coalescing operator. However, even with the notice, PHP will give the same response back.
有通知的行是我使用速记三元运算符而不是空合并运算符的行。但是,即使有通知,PHP 也会返回相同的响应。
Execute the code: https://3v4l.org/McavC
执行代码:https: //3v4l.org/McavC
Of course, this is always assuming the first argument is null
. Once it's no longer null, then you end up with differences in that the ??
operator would always return the first argument while the ?:
shorthand would only if the first argument was truthy, and that relies on how PHP would type-cast things to a boolean.
当然,这总是假设第一个参数是null
。一旦它不再为空,那么最终的区别在于??
运算符将始终返回第一个参数,而?:
简写仅在第一个参数为真时才会返回,这取决于PHP如何将事物类型转换为 boolean。
So:
所以:
$a = false ?? 'f'; // false
$b = false ?: 'g'; // 'g'
would then have $a
be equal to false
and $b
equal to 'g'
.
那么$a
将等于false
和$b
等于'g'
。
回答by a20
Ran the below on php interactive mode (php -a
on terminal). The comment on each line shows the result.
在 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"
So this is my interpretation:
所以这是我的解释:
1. The Null Coalescing Operator - ??
:
1. 空合并运算符 - ??
:
??
is like a "gate" that only lets NULL through.- So, it always returns first parameter, unless first parameter happens to be
NULL
. - This means
??
is same as( !isset() || is_null() )
??
就像一个只让 NULL 通过的“门”。- 所以,它总是返回第一个参数,除非第一个参数恰好是
NULL
。 - 这意味着
??
与( !isset() || is_null() )
2. The Ternary Operator - ?:
2. 三元运算符 - ?:
?:
is like a gate that letsanything falsy
through - includingNULL
0
,empty string
,NULL
,false
,!isset()
,empty()
.. anything that smells falsy- Just like the classic ternary operator:
echo ($x ? $x : false)
- NOTE:
?:
will throwPHP NOTICE
on undefined (unset
or!isset()
) variables
?:
就像一扇可以anything falsy
通过的门——包括NULL
0
,empty string
,NULL
,false
,!isset()
,empty()
.. 任何闻起来很假的东西- 就像经典的三元运算符:
echo ($x ? $x : false)
- 注意:
?:
将抛出PHP NOTICE
未定义的(unset
或!isset()
)变量
3. So doctor, when do I use ??
and ?:
..
3. 所以医生,我什么时候使用??
和?:
..
- I'm only joking - I'm not a doctor and this is just an interpretation
- I would use
?:
when- doing
empty($x)
checks - Classic ternary operation like
!empty($x) ? $x : $y
can be shortened to$x ?: $y
if(!$x) { fn($x); } else { fn($y); }
can be shortened tofn(($x ?: $y))
- doing
- I would use
??
when- I want to do an
!isset() || is_null()
check - e.g check if an object exists -
$object = $object ?? new objClassName();
- I want to do an
- 我只是在开玩笑 - 我不是医生,这只是一种解释
- 我会
?:
在什么时候 使用- 做
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();
- 我想做个
4. Stacking operators ...
4. 堆叠运算符...
Ternary Operator can be stacked...
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
This is basically a sequence of:
if( truthy ) {} else if(truthy ) {} else if(truthy ) {} .. else {}
Null Coalese Operator can be stacked...
$v = $x ?? $y ?? $z;
This is a sequence of:
if(!isset($x) || is_null($x) ) {} else if(!isset($y) || is_null($y) ) {} else {}
Using stacking, I can shorten this:
if(!isset($_GET['name'])){ if($user_name){ $name = $user_name; }else { $name = 'anonymous'; } } else { $name = $_GET['name']; }
To this:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
Cool, right? :-)
三元运算符可以堆叠...
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($user_name){ $name = $user_name; }else { $name = 'anonymous'; } } else { $name = $_GET['name']; }
对此:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
酷,对吧?:-)
回答by Andrew
If you use the shortcut ternary operator like this, it will cause a notice if $_GET['username']
is not set:
如果像这样使用快捷三元运算符,如果$_GET['username']
未设置,则会引起通知:
$val = $_GET['username'] ?: 'default';
So instead you have to do something like this:
所以你必须做这样的事情:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
The null coalescing operatoris equivalent to the above statement, and will return 'default' if $_GET['username']
is not set or is null
:
该空合并运算符是等同于上面的语句,将返回“默认”如果$_GET['username']
没有设置或者是null
:
$val = $_GET['username'] ?? 'default';
Note that it does not check truthiness. It checks only if it is set and not null.
请注意,它不会检查真实性。它仅检查它是否已设置且不为空。
You can also do this, and the first defined(set and not null
) value will be returned:
您也可以这样做,并且将返回第一个定义的(set 和 not null
)值:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
Now that is a proper coalescing operator.
现在这是一个合适的合并运算符。
回答by Dhairya Lakhera
The major difference is that
主要区别在于
Ternary Operatorexpression
expr1 ?: expr3
returnsexpr1
ifexpr1
evaluates toTRUE
but on the other hand Null Coalescing Operatorexpression(expr1) ?? (expr2)
evaluates toexpr1
ifexpr1
is notNULL
Ternary Operator
expr1 ?: expr3
emit a notice if the left-hand side value(expr1)
does not exist but on the other hand Null Coalescing Operator(expr1) ?? (expr2)
In particular, does not emit a notice if the left-hand side value(expr1)
does not exist, just likeisset()
.TernaryOperatoris left associative
((true ? 'true' : false) ? 't' : 'f');
Null Coalescing Operatoris right associative
($a ?? ($b ?? $c));
三元运算符表达式
expr1 ?: expr3
返回expr1
ifexpr1
评估为TRUE
但另一方面空合并运算符表达式(expr1) ?? (expr2)
评估为expr1
ifexpr1
is notNULL
expr1 ?: expr3
如果左侧值(expr1)
不存在,则三元运算符会发出通知,但另一方面,空合并运算符(expr1) ?? (expr2)
特别地,如果左侧值(expr1)
不存在,则不会发出通知,就像isset()
。三元运算符是左关联的
((true ? 'true' : false) ? 't' : 'f');
空合并运算符是右结合的
($a ?? ($b ?? $c));
Now lets explain the difference between by example :
现在让我们通过示例来解释两者之间的区别:
Ternary Operator(?:)
三元运算符(?:)
$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);
Null Coalescing Operator(??)
空合并运算符(??)
$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);
Here is the table that explain the difference and similarity between '??'
and ?:
下面是解释之间的差异性和相似性表'??'
和?:
Special Note : null coalescing operator and ternary operator is an expression, and that it doesn't evaluate to a variable, but to the result of an expression. This is important to know if you want to return a variable by reference. The statement return $foo ?? $bar; and return $var == 42 ? $a : $b; in a return-by-reference function will therefore not work and a warning is issued.
特别注意:空合并运算符和三元运算符是一个表达式,它不计算变量,而是计算表达式的结果。了解是否要通过引用返回变量很重要。语句返回 $foo ?? $bar; 并返回 $var == 42 ?$a : $b; 因此,在按引用返回的函数中将不起作用并发出警告。
回答by Chazy Chaz
Both of them behave differently when it comes to dynamic data handling.
当涉及到动态数据处理时,它们两者的行为都不同。
If the variable is empty ( '' ) the null coalescing will treat the variable as true but the shorthand ternary operator won't. And that's something to have in mind.
如果变量为空 ( '' ),则空合并会将变量视为真,但速记三元运算符不会。这是需要牢记的。
$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';
And the output:
和输出:
1b
2b
2d
1f
Notice: Undefined variable: e in /in/ZBAa1 on line 21
2f
Link: https://3v4l.org/ZBAa1
回答by Dean Or
Both are shorthands for longer expressions.
两者都是较长表达式的简写。
?:
is short for $a ? $a : $b
. This expression will evaluate to $a if $a evaluates to TRUE.
?:
是 的缩写$a ? $a : $b
。如果 $a 的计算结果为TRUE ,则此表达式的计算结果为 $a 。
??
is short for isset($a) ? $a : $b
. This expression will evaluate to $a if $a is set and not null.
??
是 的缩写isset($a) ? $a : $b
。如果设置了 $a 且不为空,则此表达式的计算结果为 $a。
Their use cases overlaps when $a is undefined or null. When $a is undefined ??
will not produce an E_NOTICE, but the results are the same. When $a is null the result is the same.
当 $a 未定义或为空时,它们的用例会重叠。当 $a 未定义??
时不会产生 E_NOTICE,但结果是一样的。当 $a 为空时,结果相同。
回答by Supun Praneeth
For the beginners:
对于初学者:
Null coalescing operator (??)
空合并运算符 (??)
Everything is true except null
values and undefined (variable/array index/object attributes)
除了null
值和未定义(变量/数组索引/对象属性)之外,一切都是真的
ex:
前任:
$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"
this is basically check the variable(array index, object attribute.. etc) is exist and not null
. similar to isset
function
这基本上是检查变量(数组索引、对象属性等)是否存在null
。类似于isset
功能
Ternary operator shorthand (?:)
三元运算符简写 (?:)
every false things (false
,null
,0
,empty string) are come as false, but if it's a undefined it also come as false but Notice
will throw
每一个虚假的东西(false
,null
,0
,空字符串)都是来作为假的,但如果它是一个不确定的,也都为假,但Notice
会抛出
ex
前任
$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: ..
Hope this helps
希望这可以帮助
回答by Script47
Scroll down on thislink and view the section, it gives you a comparative example as seen below:
向下滚动此链接并查看该部分,它为您提供了一个比较示例,如下所示:
<?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';
?>
However, it is not advised to chain the operators as it makes it harder to understand the code when reading it later on.
但是,不建议将运算符链接起来,因为它会使以后阅读代码时更难理解。
The null coalescing operator (??) has been added as syntactic sugar for the common case of needing to use a ternary in conjunction with isset(). It returns its first operand if it exists and is not NULL; otherwise it returns its second operand.
空合并运算符 (??) 已被添加为语法糖,用于需要将三元与 isset() 结合使用的常见情况。如果存在且不为 NULL,则返回其第一个操作数;否则它返回它的第二个操作数。
Essentially, using the coalescing operator will make it auto check for null unlike the ternary operator.
本质上,与三元运算符不同,使用合并运算符将使其自动检查 null。
回答by Yaron U.
The other answers goes deep and give great explanations. For those who look for quick answer,
其他答案很深入,并给出了很好的解释。对于那些寻求快速答案的人,
$a ?: 'fallback'
is $a ? $a : 'fallback'
$a ?: 'fallback'
是 $a ? $a : 'fallback'
while
尽管
$a ?? 'fallback'
is $a = isset($a) ? $a : 'fallback'
$a ?? 'fallback'
是 $a = isset($a) ? $a : 'fallback'
The main difference would be when the left operator is either:
主要区别在于左运算符是:
- A falsy value that is NOT null (
0
,''
,false
,[]
, ...) - An undefined variable
- 一个非空的假值 (
0
,''
,false
,[]
, ...) - 未定义的变量
回答by Damian Green
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
.
使用??
或似乎有利有弊?:
。使用的优点?:
是它评估 false 和 null 和 "" 相同。缺点是如果前面的参数为空,它会报告 E_NOTICE。随着??
亲是没有E_NOTICE,但con是,它不评估虚假和无效一样。根据我的经验,我看到人们开始交替使用 null 和 false,但后来他们最终会修改他们的代码以与使用 null 或 false 保持一致,但不能同时使用两者。另一种方法是创建一个更复杂的三元条件:(isset($something) or !$something) ? $something : $something_else
.
The following is an example of the difference of using the ??
operator using both null and false:
以下是??
使用 null 和 false的运算符的区别示例:
$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---
$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---
By elaborating on the ternary operator however, we can make a false or empty string "" behave as if it were a null without throwing an e_notice:
然而,通过详细说明三元运算符,我们可以使一个假的或空的字符串 "" 表现得好像它是一个 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---
Personally, I think it would be really nice if a future rev of PHP included another new operator: :?
that replaced the above syntax. ie:
// $var = $false :? "true";
That syntax would evaluate null, false, and "" equally and not throw an E_NOTICE...
就我个人而言,我认为如果 PHP 的未来版本包含另一个新的运算符会非常好::?
它取代了上述语法。即:
// $var = $false :? "true";
该语法将相等地评估 null、false 和 "" 并且不会抛出 E_NOTICE ...