有人可以解释三元操作速记之间的差异( ?:
和空合并运算符() ??
在PHP)?
他们什么时候表现不同,当以相同的方式(如果连发生)?
$a ?: $b
VS.
$a ?? $b
有人可以解释三元操作速记之间的差异( ?:
和空合并运算符() ??
在PHP)?
他们什么时候表现不同,当以相同的方式(如果连发生)?
$a ?: $b
VS.
$a ?? $b
当你的第一个参数为空,他们基本上只是空合并不会输出相同E_NOTICE
当你有一个未定义的变量。 在PHP 7.0迁移的文档有这样一段话:
的空合并运算符(??)已经被添加作为语法糖为需要结合使用的三元与isset的常见的情况()。 如果存在且不是NULL,它返回它的第一个操作数; 否则返回第二个操作数。
下面是一些例子代码来证明这一点:
<?php
$a = null;
print $a ?? 'b';
print "\n";
print $a ?: 'b';
print "\n";
print $c ?? 'a';
print "\n";
print $c ?: 'a';
print "\n";
$b = array('a' => null);
print $b['a'] ?? 'd';
print "\n";
print $b['a'] ?: 'd';
print "\n";
print $b['c'] ?? 'e';
print "\n";
print $b['c'] ?: 'e';
print "\n";
而且它的输出:
b
b
a
Notice: Undefined variable: c in /in/apAIb on line 14
a
d
d
e
Notice: Undefined index: c in /in/apAIb on line 33
e
有通知的行是我使用的是速记三元运算符,而不是空合并运算符的人。 然而,即使该通知,PHP会给出相同的响应返回。
执行代码: https://3v4l.org/McavC
当然,这是假设总是第一个参数是null
。 一旦它不再为空,那么你最终在差异??
运营商将始终返回的第一个参数,而?:
速记只会如果第一个参数是truthy,并且依赖于如何PHP将类型转换的东西为布尔值 。
所以:
$a = false ?? 'f';
$b = false ?: 'g';
然后将有$a
等于false
和$b
等于'g'
。
如果您使用快捷三元运算符这样,就会造成一个通知,如果$_GET['username']
没有设置:
$val = $_GET['username'] ?: 'default';
因此,你必须做这样的事情:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
空合并运算符相当于上面的语句,将返回“默认”如果$_GET['username']
未设置或为null
:
$val = $_GET['username'] ?? 'default';
需要注意的是它不检查感实性 。 如果它被设置,而不是空它只检查。
你也可以做到这一点,第一定义 (设置,而不是null
)值将返回:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
现在是一个合适的合并运算符。
主要的区别是,
三元运算符表达式expr1 ?: expr3
返回expr1
如果expr1
计算为TRUE
,但是,从另一方面空合并运算符表达式(expr1) ?? (expr2)
(expr1) ?? (expr2)
的计算结果为expr1
如果expr1
不是 NULL
三元运算 expr1 ?: expr3
发出通知,如果左侧值(expr1)
不存在,但是,从另一方面空合并运算符 (expr1) ?? (expr2)
(expr1) ?? (expr2)
特别是,不发射的通知,如果左手侧值(expr1)
不存在,就像isset()
。
TernaryOperator是左结合
((true ? 'true' : false) ? 't' : 'f');
空合并运算符是右结合
($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);
下面是解释之间的差异和相似性表'??'
和?:
特别提示:空合并运算符和三元运算符是一个表达式,它不计算为一个变量,而是一个表达式的结果。 这一点很重要要知道,如果你想通过引用返回一个变量。 该语句返回$ foo的? $酒吧; 和回报是$ var == 42? $ A:$ B; 因此在返回按引用功能将无法正常工作,并发出警告。
然下面的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
!empty($x) ? $x : $y
可缩短至$x ?: $y
if(!$x) { fn($x); } else { fn($y); }
if(!$x) { fn($x); } else { fn($y); }
可缩短到fn(($x ?: $y))
??
什么时候 !isset() || is_null()
!isset() || is_null()
检查 $object = $object ?? new objClassName();
$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 {}
空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';
酷吧? :-)
他们两人的表现不同,当涉及到动态数据处理。
如果变量是空的(“”)的空合并将把该变量为真,但速记三元运营商不会。 而这东西的想法。
$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 ? $a : $b
。 如果$ a的值为TRUE这个表达式会$一个。
??
是短期的isset($a) ? $a : $b
isset($a) ? $a : $b
。 如果$ a设置,而不是null,则此表达式的值为$一个。
当$一个未定义或空它们的使用情况下重叠。 当$一个未定义??
不会产生E_NOTICE,但结果是一样的。 当$ a是空的结果是一样的。
向下滚动,在此链接,查看部分,它给你一个比较例子,如下图所示:
<?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';
?>
然而,因为它使稍后阅读时,它变得很难理解它的代码是不建议链运营商。
的空合并运算符(??)已经被添加作为语法糖为需要结合使用的三元与isset的常见的情况()。 如果存在且不是NULL,它返回它的第一个操作数; 否则返回第二个操作数。
从本质上讲,使用合并运算符将使不像三元运算符为null,则自动检查。
这似乎有利弊,无论是使用??
或?:
。 临去使用?:
是它判断为假,零和“”一样。 con是,如果它前面的参数为空报告的E_NOTICE。 随着??
亲是没有E_NOTICE,但con是,它不评估虚假和无效一样。 根据我的经验,我看到人们开始使用空,假的互换,但随后他们最终求助于修改自己的代码是用null或false一致的,但不能同时使用。 另一种方法是创建一个更复杂的三元条件: (isset($something) or !$something) ? $something : $something_else
(isset($something) or !$something) ? $something : $something_else
。
以下是使用的差异的例子??
同时使用空,假的操作:
$false = null;
$var = $false ?? "true";
echo $var . "---<br>";//returns: true---
$false = false;
$var = $false ?? "true";
echo $var . "---<br>"; //returns: ---
然而,通过详细阐述了三元运算符,我们可以做一个虚假或空字符串“”行为,如果它是一个空未抛出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---
就个人而言,我认为这将是非常好的,如果未来PHP的转包含另一个新的运营商: :?
取代了上述语法。 即: // $var = $false :? "true";
// $var = $false :? "true";
这句法将评估空,假的,“”平等,而不是抛出一个E_NOTICE ...
class a
{
public $a = 'aaa';
}
$a = new a();
echo $a->a; // Writes 'aaa'
echo $a->b; // Notice: Undefined property: a::$b
echo $a->a ?? '$a->a does not exists'; // Writes 'aaa'
// Does not throw an error although $a->b does not exist.
echo $a->b ?? '$a->b does not exist.'; // Writes $a->b does not exist.
// Does not throw an error although $a->b and also $a->b->c does not exist.
echo $a->b->c ?? '$a->b->c does not exist.'; // Writes $a->b->c does not exist.
Null Coalescing operator
执行只有两个任务:它检查whether the variable is set
以及whether it is null
。 看看下面的例子:
<?php
# case 1:
$greeting = 'Hola';
echo $greeting ?? 'Hi There'; # outputs: 'Hola'
# case 2:
$greeting = null;
echo $greeting ?? 'Hi There'; # outputs: 'Hi There'
# case 3:
unset($greeting);
echo $greeting ?? 'Hi There'; # outputs: 'Hi There'
上面的代码示例指出Null Coalescing operator
对待一个不存在的变量和其被设置为变量NULL
以相同的方式。
Null Coalescing operator
是在改善ternary operator
。 看一看下面的代码段两相比较:
<?php /* example: checking for the $_POST field that goes by the name of 'fullname'*/
# in ternary operator
echo "Welcome ", (isset($_POST['fullname']) && !is_null($_POST['fullname']) ? $_POST['fullname'] : 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.
# in null coalecing operator
echo "Welcome ", ($_POST['fullname'] ?? 'Mr. Whosoever.'); # outputs: Welcome Mr. Whosoever.
因此,两者之间的区别是, Null Coalescing operator
操作被设计用来处理未定义的变量好过ternary operator
。 然而,对ternary operator
是简写if-else
。
Null Coalescing operator
并不意味着更换ternary operator
,但在某些情况下,使用像在上面的例子中,它可以让你写干净的代码少些麻烦。
积分: http://dwellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples
当使用像$ _GET或$ _REQUEST超全局,你应该知道,他们可能是一个空字符串。 在这种情况下specal这个例子
$username = $_GET['user'] ?? 'nobody';
将失败,因为$ username的值现在是一个空字符串。
因此,使用$ _GET甚至$ _REQUEST你应该使用三元运算,而不是像这样的时候:
$username = (!empty($_GET['user'])?$_GET['user']:'nobody';
现在$用户名的值是“没人”预期。