本篇為PHP系列
兩個問號 ??
及問號冒號 ?:
的差別其實不大,兩者在使用方式上的差異,主要在於什麼時候回傳第二個變數。
三元運算子
要聊 ??
跟 ?:
不得不先提一下三元運算子 (ternary),三元運算子的用法是像這樣:
$a ? $a : $b;
如果 $a
可以被視為 TRUE
時,則回傳 $a
,若 $a
被視為 FALSE
時,則回傳 $b
。
大概是這樣的感覺:
if ($a) {
return $a;
} else {
return $b;
}
當然也可以這樣寫:
$a ? $b : $c;
那就是這樣的意思:
if ($a) {
return $b;
} else {
return $c;
}
哪些值可以被視為 true 或 false,可以參考: PHP type comparison tables。
基本上常見的空字串""
、null
、0
、空陣列[]
等,都算是 FALSE
。
??
運算子 Null Coalescing Operator
兩個問號 ??
其實就是Null coalescing operator
,直接翻譯是 null連接運算子
(真的是??)。
那這個東西其實是 PHP 7 之後才有的新功能,擷取官方說明文件的說明:
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.
稍微翻譯一下這段話如下:
對於需要結合三元運算子及
isset()
的常見使用案例,null coalescing operator
已經作為一個語法糖被加入 PHP 了。如果第一個運算元存在且不是 NULL ,就會回傳第一個運算元,否則就會回傳第二個。
總結而言, ??
是 ?:
搭配 isset()
使用的語法糖。
換句話說:如果第一個變數的 isset 檢查通過(變數存在且非 NULL),那就會回傳第一個變數,否則則回傳第二個,
舉個例子來說,原本我們想要判斷第一個變數有沒有存在,若沒有則回傳第二個,使用傳統的三元運算子,寫法會像是:
isset($a) ? $a : $b;
其實也就等同於這樣的感覺:
if (isset($a)) {
return $a;
} else {
return $b;
}
有了null coalescing operator
以後,可以簡化成:
$a ?? $b;
另外,由於 isset()
的定義是:
Determine if a variable is declared and is different than NULL。
所以只有同時滿足這兩個條件:
- 變數有被宣告
- 其值不是
NULL
isset()
才會回傳TRUE
。
也就是說,即便該變數有宣告,但它的值卻是 NULL
,isset()
也會是 FALSE
。
看看實際的案例:
/// 1. $a不存在,回傳第二個運算元$b的值"b"。
$b = "b";
var_dump($a ?? $b); // "b"
// 2. $a存在,且不為NULL,回傳$a的值"a"。
$a = "a";
var_dump($a ?? $b); // "a"
// 3. $a存在,且不為NULL(false !== NUll),回傳$a目前的值false。
$a = false;
var_dump($a ?? $b); // false
// 4. $a存在,卻為NULL,回傳$b的值"b"。
$a = null;
var_dump($a ?? $b); // "b"
// 5. 由左讀到右,$a、$b、$c都是NULL,所以都回傳$d的值"d"。
$a = null;
$b = null;
$c = null;
$d = "d";
var_dump($a ?? $b ?? $c ?? $d); // "d"
var_dump($a ?? $b ?? $c ?? $d ?? $e); // "d"
?:
運算子
?:
其實是短版的三元運算子(shorthand ternary operator
)。
有些時候我們並不需要用到三個變數:
$a ? $a : $b;
這種就可以用 ?:
來省略:
$a ?: $b;
所以 ??
跟 ?:
最大的差異其實就是 isset()
而已。
??
→ 第一個變數是 null 或未宣告,回傳第二個變數,否則回傳第一個。
?:
→ 第一個變數是等同於 False,回傳第二個變數,否則回傳第一個。
再比較一下 ?:
跟 ??
PHP Notice
?:
遇到未宣告的變數會跳 PHP Notice
:
<?php
$b = "b";
echo $a ?: $b;
PHP Notice: Undefined variable: a
但是 ??
不會跳 PHP Notice
:
<?php
$b = "b";
echo $a ?? $b;
"b"
對於 false 的判斷
<?php
$a = false;
$b = "b";
var_dump($a ?: $b); // "b"
var_dump($a ?? $b); // false
參考資料
看更多PHP系列