PHP三元操作VS空合并运算符PHP三元操作VS空合并运算符(PHP ternary operato

2019-05-11 05:42发布

有人可以解释三元操作速记之间的差异( ?:和空合并运算符() ??在PHP)?

他们什么时候表现不同,当以相同的方式(如果连发生)?

$a ?: $b

VS.

$a ?? $b

Answer 1:

当你的第一个参数为空,他们基本上只是空合并不会输出相同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'



Answer 2:

如果您使用快捷三元运算符这样,就会造成一个通知,如果$_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';

现在是一个合适的合并运算符。



Answer 3:

主要的区别是,

  1. 三元运算符表达式expr1 ?: expr3返回expr1如果expr1计算为TRUE ,但是,从另一方面空合并运算符表达式(expr1) ?? (expr2) (expr1) ?? (expr2)的计算结果为expr1如果expr1 不是 NULL

  2. 三元运算 expr1 ?: expr3发出通知,如果左侧值(expr1)不存在,但是,从另一方面空合并运算符 (expr1) ?? (expr2) (expr1) ?? (expr2)特别是,不发射的通知,如果左手侧值(expr1)不存在,就像isset()

  3. 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; 因此在返回按引用功能将无法正常工作,并发出警告。



Answer 4:

然下面的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"

因此,这是我的解释:

1.空合并运算符- ??

  • ?? 就像是“门”,仅允许通过NULL。
  • 因此, 它总是返回第一个参数 ,除非第一个参数恰好是NULL
  • 这意味着?? 是一样的( !isset() || is_null() )

2.三元运算符- ?:

  • ?:就像是一个门,让anything falsy经过-包括NULL
  • 0empty stringNULLfalse!isset()empty() ..任何气味falsy
  • 就像经典的三元运算符: echo ($x ? $x : false)
  • 注: ?:将抛出PHP NOTICE未定义( unset!isset() )变量

3.所以,医生,什么时候使用???: ..

  • 我只是在开玩笑 - 我不是医生,这只是一个解释
  • 我会用?:
    • 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();

4.堆叠运营商...

  1. 三元操作员可以堆叠 ...

     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 {} 
  2. 空Coalese操作员可堆叠 ...

     $v = $x ?? $y ?? $z; 

    这是一个序列:

     if(!isset($x) || is_null($x) ) {} else if(!isset($y) || is_null($y) ) {} else {} 
  3. 使用堆叠,我可以缩短这个:

     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'; 

    酷吧? :-)



Answer 5:

他们两人的表现不同,当涉及到动态数据处理。

如果变量是空的(“”)的空合并将把该变量为真,但速记三元运营商不会。 而这东西的想法。

$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



Answer 6:

两者都是长表达式速记。

?:是短期的$a ? $a : $b $a ? $a : $b 。 如果$ a的值为TRUE这个表达式会$一个。

?? 是短期的isset($a) ? $a : $b isset($a) ? $a : $b 。 如果$ a设置,而不是null,则此表达式的值为$一个。

当$一个未定义或空它们的使用情况下重叠。 当$一个未定义?? 不会产生E_NOTICE,但结果是一样的。 当$ a是空的结果是一样的。



Answer 7:

向下滚动,在此链接,查看部分,它给你一个比较例子,如下图所示:

<?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,则自动检查。



Answer 8:

这似乎有利弊,无论是使用???: 。 临去使用?:是它判断为假,零和“”一样。 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 ...



Answer 9:

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.


Answer 10:

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



Answer 11:

当使用像$ _GET或$ _REQUEST超全局,你应该知道,他们可能是一个空字符串。 在这种情况下specal这个例子

$username = $_GET['user'] ?? 'nobody';

将失败,因为$ username的值现在是一个空字符串。

因此,使用$ _GET甚至$ _REQUEST你应该使用三元运算,而不是像这样的时候:

$username = (!empty($_GET['user'])?$_GET['user']:'nobody';

现在$用户名的值是“没人”预期。



文章来源: PHP ternary operator vs null coalescing operator