PHP运算符 ?? vs ?:
PHP中的操作符??和?:的出现是为了解决以下问题。如果使用简化的三元运算符,当$_GET['username']未设置时会引发一个提示:
$val = $_GET['username'] ?: 'default';
因此,你需要像这样处理:
$val = isset($_GET['username']) ? $_GET['username'] : 'default';
而null合并运算符等效于上面的语句,并且如果$_GET['username']未设置或为null,则返回'default':
$val = $_GET['username'] ?? 'default';
注意,它不检查真实性。它只检查它是否设置且不为null。
你也可以这样做,返回第一个已定义(设置且不为null)的值:
$val = $input1 ?? $input2 ?? $input3 ?? 'default';
现在这是一个合适的合并运算符。
为了不引发提示,应该使用$var = empty($other_var) ? 'default_value' : $other_var;
。注意,这不包括''、null、false和0。
PHP中的运算符??和?:之间的区别以及出现的原因和解决方法
在PHP交互模式下运行了下面的代码(在终端上运行php -a)。每一行的注释显示了结果。
var_export (false ?? 'value2'); // false var_export (true ?? 'value2'); // true var_export (null ?? 'value2'); // value2 var_export ('' ?? 'value2'); // "" var_export (0 ?? 'value2'); // 0 var_export (false ?: 'value2'); // value2 var_export (true ?: 'value2'); // true var_export (null ?: 'value2'); // value2 var_export ('' ?: 'value2'); // value2 var_export (0 ?: 'value2'); // value2
**Null合并运算符 `??`**
- `??`类似于一个“门”,只允许`NULL`通过。
- 所以,除非第一个参数恰好是`NULL`,否则它总是返回第一个参数。
- 这意味着`??`与`( !isset() || is_null() )`相同。
使用`??`的方式:
- 缩短`!isset() || is_null()`的检查。
- 例如:`$object = $object ?? new objClassName();`
堆叠Null合并运算符:
$v = $x ?? $y ?? $z; // 这是一系列“SET && NOT NULL”: if($x && !is_null($x)){ return $x; } else if($y && !is_null($y)){ return $y; } else { return $z; }
**三元运算符 `?:`**
- `?:`类似于一个门,可以让任何“假值”通过 - 包括`NULL`。
- 任何“假值”:`0`,空字符串,`NULL`,`false`,`!isset()`,`empty()`
- 与旧的三元运算符相同:`X ? Y : Z`
- 注意:对于未定义(未设置或`!isset()`)的变量,`?:`会抛出PHP NOTICE。
使用`?:`的方式:
- 检查`empty()`,`!isset()`,`is_null()`等。
- 将三元操作缩短为`!empty($x) ? $x : $y`,变为`$x ?: $y`。
- 将`if(!$x) { echo $x; } else { echo $y; }`缩短为`echo $x ?: $y`。
堆叠三元运算符:
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(isset($_GET['name']) && !is_null($_GET['name'])) { $name = $_GET['name']; } else if(!empty($user_name)) { $name = $user_name; } else { $name = 'anonymous'; }
缩短为:
$name = $_GET['name'] ?? $user_name ?: 'anonymous';
很酷,对吧? 🙂
这种方法很好,只是有一个错误:将`if(!$x) { echo $x; } else { echo $y; }`缩短为`echo $x ?: $y`。两者是不相等的。条件必须是`if($x)`,没有否定。这个例子让我了解了这个新的运算符的一些知识,所以我给了一个赞。
在PHP中,请始终使用`elseif`作为一个单词,以符合PSR-12编码规范。我知道你只是在做一个演示,但是`isset($_GET['name']) && !is_null($_GET['name'])`本身就是冗余的检查。
这是一个非常好的解释,但不要错过这一行:`Note: ?: will throw PHP NOTICE on undefined (unset or !isset()) variables`,如果无法保证一个变量(尤其是一个数组索引)已经设置,仍然需要使用`!empty()`或`isset()`(取决于你需要的行为)。
PHP运算符??和?:的区别以及解决方法
在PHP中,Elvis运算符`?:`和Null合并运算符`??`的作用是相似的,都是用来简化代码中的条件表达式。然而,它们之间存在一些细微的差别。
Elvis运算符`?:`会返回第一个参数,如果第一个参数包含一个“真值”(参见PHP手册中“Loose comparisons with ==”表中哪些值被松散地等同于`true`),否则返回第二个参数。它的语法如下:
$result = $var ?: 'default'; //等同于 $result = $var ? $var : 'default';
Null合并运算符`??`会返回第一个参数,如果第一个参数已经设置并且不为`null`,否则返回第二个参数。它的语法如下:
$result = $var ?? 'default'; //等同于 $result = isset($var) ? $var : 'default';
当第一个参数为`null`时,它们基本上是相同的,唯一的区别是当使用未定义的变量时,Null合并运算符不会输出一个`E_NOTICE`错误。根据PHP 7.0的迁移文档,Null合并运算符是为了简化在使用`isset()`函数进行判断的情况而添加的。如果第一个操作数存在且不为`NULL`,它返回第一个操作数;否则返回第二个操作数。
下面是一些示例代码来演示这一点:
$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";
以上代码中,使用`??`运算符的地方不会出现Notice错误,而使用`?:`运算符的地方会出现Notice错误。然而,即使有Notice错误,PHP也会返回相同的结果。
当第一个参数不为`null`时,它们之间的区别就显现出来了。Null合并运算符`??`将始终返回第一个参数,而Elvis运算符`?:`只有在第一个参数为真值时才会返回第一个参数,这依赖于PHP如何将值转换为布尔类型。
例如:
$a = false ?? 'f'; // $a的值为 false $b = false ?: 'g'; // $b的值为 'g'
需要注意的是,Null合并运算符`??`可以进行链式操作。例如:
$b = []; var_dump($b['a']['b']['c'] ?? 'default'); // 输出 'default'
或者在对象中使用:
$b = new Foo; var_dump($b->a()->b()->c() ?? 'default'); // 输出 'default'
需要注意的是,对于`$a = [];`的情况,它们的行为也是不同的。可以参考链接:[3v4l.org/iCCa0](https://3v4l.org/iCCa0)
,Elvis运算符`?:`和Null合并运算符`??`在某些情况下可以互换使用,但在一些特定的情况下存在细微的差别。根据具体的需求和代码兼容性,选择合适的运算符来简化代码。