曾經踩過的 PHP 一個小坑:null 合併運算子 ??

cn-five發表於2020-08-22

什麼是 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 協議》,轉載必須註明作者和本文連結

相關文章