曾经踩过的 PHP 一个小坑:null 合并运算符 ??

什么是 null 合并运算符?

由于在日常使用中会使用大量的三元表达式(比如 ThinkPHP 框架)和 isset() 的场景, PHP 7 增加了 null 合并运算符 ??。变量存在且值不为 null ,它就会返回自身的值,否则返回它的第二个操作数。简化了代码,提升了效率。

$_SESSION['user'] ?? 'none';

等价于

isset($_SESSION['user']) ? $_SESSION['user'] : 'none';

但一次在工作中不小心踩了一个坑,逻辑是这样的:如果返回值为空,则使用第二个操作数。但是实际明知返回值为空的情况下,却始终拿不到第二个操作数的值。
原因是把 nullfalse 、空字符串等价了。

$arr = [false, '', 0, 0.0];

foreach ($arr as $v) {
    echo empty($v) . '<br />';
    echo (null == $v) . '<br />';
}

以上代码输出结果全为 1 ,表明在 null 与这些数据类型在使用 == 运算符的情况下是等价的。但 isset() 只认变量值是否为 null ,只有在变量值被设置且为 null 的情况下才返回第二个操作数。
但是有种情况会有一种麻痹作用,那就是逻辑上如果变量被设置且为 null 就返回一个空字符串。虽然语法和结果都正确,但实际是一段有瑕疵的代码。

// 如果 session 值不存在就返回空值,实际上返回的是 session 的空值
// 虽然结果正确,只是碰巧而已
isset($_SESSION['user']) ? $_SESSION['user'] : '';

如果采用考虑数据类型的 === 强等于运算符,结果则都为 false

$arr = [false, '', 0, 0.0];

foreach ($arr as $v) {
    echo (null === $v) . '<br />';
}

如果确定变量被设置且为 null ,推荐使用 ?? 。如果不确定则使用 empty()

!empty($_SESSION['user']) ? $_SESSION['user'] : '';

但是 empty() “杀伤力”不小,尤其是在处理与数据库有关的业务中,慎用 empty() 。例如

if(!empty($data['params'])) {
    $update['id'] = ltrim($data['params']);
}

因为数据库的表中有的字段数据值可以是 0 以及字符串类型 "0" 等等 。所以此时采用 isset() 为佳。

if(isset($data['params'])) {
    $update['id'] = ltrim($data['params']);
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 1

有踩过,关于 false、null 和 0

2年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!