PHP ternary operator vs null coalescing operator
有人能解释PHP中三元运算符速记(
他们什么时候行为不同,什么时候以同样的方式(如果这种情况发生的话)?
1 | $a ?: $b |
VS
1 | $a ?? $b |
当第一个参数为空时,它们基本上是相同的,只是当您有一个未定义的变量时,空合并不会输出一个
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.
下面是一些示例代码来演示这一点:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <?php $a = null; print $a ?? 'b'; print" "; print $a ?: 'b'; print" "; print $c ?? 'a'; print" "; print $c ?: 'a'; print" "; $b = array('a' => null); print $b['a'] ?? 'd'; print" "; print $b['a'] ?: 'd'; print" "; print $b['c'] ?? 'e'; print" "; print $b['c'] ?: 'e'; print" "; |
它的输出:
1 2 3 4 5 6 7 8 9 10 11 12 | 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
当然,这总是假设第一个参数是
所以:
1 2 | $a = false ?? 'f'; $b = false ?: 'g'; |
那么,
如果您使用这样的快捷方式三元运算符,如果没有设置
1 | $val = $_GET['username'] ?: 'default'; |
因此,你必须这样做:
1 |
空合并运算符等价于上述语句,如果
1 | $val = $_GET['username'] ?? 'default'; |
请注意,它不检查真实性。它只检查是否已设置且不为空。
您也可以这样做,并且将返回第一个定义的(set和not
1 | $val = $input1 ?? $input2 ?? $input3 ?? 'default'; |
现在这是一个适当的合并操作符。
主要区别在于
三元运算符表达式
三元的如果左侧值
三元运算符是左关联的
1 | ((true ? 'true' : false) ? 't' : 'f'); |
空合并运算符是右关联的
1 | ($a ?? ($b ?? $c)); |
现在让我们通过示例来解释这两者之间的区别:
三元运算符
1 2 3 4 5 6 7 8 9 10 11 12 |
空合并运算符
1 2 3 4 5 6 7 8 9 10 11 |
这是解释
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.
在php交互模式(终端上的
1 2 3 4 5 6 7 8 9 10 11 | 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 。 - 这意味着
?? 与( !isset() || is_null() ) 相同。
2。三元运算符-
?: 就像一扇大门,让anything falsy 通过,包括NULL 在内。0 、empty string 、NULL 、false 、!isset() 、empty() 。任何闻起来有问题的东西- 就像经典的三元运算符:
echo ($x ? $x : false) 。 - 注:
?: 将在未定义(unset 或!isset() 变量上抛出PHP NOTICE 。
三。医生,我什么时候用
- 我只是开玩笑-我不是医生,这只是个解释
- 我会用
?: 当- 做
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。堆叠运算符…
三元运算符可以叠加…
1 2 3 4 5 6 7 8 | 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 |
此代码的源代码和信用
这基本上是一个序列:
1 2 3 4 5 | if( truthy ) {} else if(truthy ) {} else if(truthy ) {} .. else {} |
可以堆叠空coalese运算符…
1 | $v = $x ?? $y ?? $z; |
这是一系列:
使用堆叠,我可以缩短:
1 2 3 4 5 6 7 8 9 |
对此:
1 | $name = $_GET['name'] ?? $user_name ?: 'anonymous'; |
酷,对吧?-)
当涉及到动态数据处理时,它们的行为都不同。
如果变量为空(""),则空合并将把该变量视为真,而速记三元运算符则不会。这是需要考虑的问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | $a = NULL; $c = ''; print $a ?? '1b'; print" "; print $a ?: '2b'; print" "; print $c ?? '1d'; print" "; print $c ?: '2d'; print" "; print $e ?? '1f'; print" "; print $e ?: '2f'; |
输出:
1 2 3 4 5 6 7 8 | 1b 2b 2d 1f Notice: Undefined variable: e in /in/ZBAa1 on line 21 2f |
链接:https://3v4l.org/zbaa1
这两个词都是长句的简称。
当$A未定义或为空时,它们的用例会重叠。当$A未定义时,
向下滚动此链接并查看该部分,它提供了如下所示的比较示例:
1 2 3 4 5 6 7 8 9 | <?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'; ?> |
但是,不建议将运算符链接起来,因为这样在以后读取代码时更难理解代码。
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.
本质上,使用合并运算符将使其自动检查是否为空,这与三元运算符不同。
使用
下面是使用
1 2 3 4 5 6 7 | $false = null; $var = $false ??"true"; echo $var ."---";//returns: true--- $false = false; $var = $false ??"true"; echo $var ."---"; //returns: --- |
然而,通过对三元运算符的详细说明,我们可以使一个假字符串或空字符串"表现得像一个空字符串,而不抛出e_通知:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | $false = null; $var = (isset($false) or !$false) ? $false :"true"; echo $var ."---";//returns: --- $false = false; $var = (isset($false) or !$false) ? $false :"true"; echo $var ."---";//returns: --- $false =""; $var = (isset($false) or !$false) ? $false :"true"; echo $var ."---";//returns: --- $false = true; $var = (isset($false) or !$false) ? $false :"true"; echo $var ."---";//returns: 1--- |
我个人认为,如果将来的PHP版本中包含另一个新的操作符:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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. |
当使用诸如$u get或$u请求之类的超全局变量时,您应该注意它们可能是空字符串。在这个特殊情况下,这个例子
1 | $username = $_GET['user'] ?? 'nobody'; |
将失败,因为$username的值现在是空字符串。
因此,当使用$u get或甚至$u请求时,您应该使用三元运算符,而不是如下所示:
1 |
现在$username的值如预期的"nobody"。
1 2 3 4 5 6 7 8 9 10 11 12 | <?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' |
上面的代码示例说明,
1 2 3 4 5 | <?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. |
因此,两者之间的区别在于,
学分:http://bellupper.io/post/6/php7-null-coalescing-operator-usage-and-examples