細かい部分を若干間違えて覚えており、危うくバグを出すところだったので、きちんと調べ直しました。
エルビス演算子 ?:
公式サイトには単体での説明はなく、三項演算子の項目に説明がありました。PHP 5.3 以降で使用可能です。
式 expr1 ?: expr3 の結果は、expr1 が TRUE と同等の場合は expr1、 それ以外の場合は expr3 となります。
要するに、expr1 ? expr1 : expr3
のシンタックスシュガーということですね。
Null 合体演算子 ??
こちらは独立した項目として説明されていました。PHP 7 以降で使用可能です。
式 (expr1) ?? (expr2) は、 expr1 が NULL である場合は expr2 と評価され、それ以外の場合は expr1 と評価されます。
この演算子は、左側の値が存在しない場合でも notice が発生しません。
isset(expr1) ? expr1 : expr2
と同様の結果になります。
expr1がNULLや未定義でなければexpr1と評価されるので、falsyな値になる場合もあります。1
【2020/4/8 追記】
いただいたコメントによると「issetはgetterによる値の取得を試行しない」とのことで、正しくは 「!is_null(expr1) ? expr1 : expr2
と同様」のようです。
色々な値で検証してみる
以前、PHP/JavaScriptの真偽と型という記事で色々な値の真偽を調べましたが、その時と同様のデータで2つの演算子の結果を調べてみました。
$aの値 | エルビス演算子$a ?: $b
|
Null合体演算子$a ?? $b
|
---|---|---|
TRUE | TRUE | TRUE |
FALSE | $bの値 | FALSE |
-1 | -1 | -1 |
0 | $bの値 | 0 |
1 | 1 | 1 |
-0.1 | -0.1 | -0.1 |
0.0 | $bの値 | 0.0 |
0.1 | 0.1 | 0.1 |
文字列 'a' | 'a' | 'a' |
空文字列 '' | $bの値 | '' |
文字列のゼロ '0' | $bの値 | '0' |
NULL | $bの値 | $bの値 |
空の配列 array() | $bの値 | array() |
空でない配列 array(0) | array(0 => 0) | array(0 => 0) |
空のオブジェクト new stdClass() | stdClass::__set_state(array( )) | stdClass::__set_state(array( )) |
未定義の変数 $none |
$bの値 ( Notice: Undefined variable が発生し、nullとして評価された結果) |
$bの値 (Noticeは発生しない) |
未定義のインデックス $my_array['none'] |
$bの値 ( Notice: Undefined index が発生し、nullとして評価された結果) |
$bの値 (Noticeは発生しない) |
未定義のプロパティ $my_object->none |
$bの値 ( Notice: Undefined property が発生し、nullとして評価された結果) |
$bの値 (Noticeは発生しない) |
表にはありませんが、エルビス演算子が$a ? $a : $b
と同じで、Null合体演算子とisset($a) ? $a : $b
が同じ結果になることも検証してあります。
$aが未定義の可能性がある場合は、エルビス演算子を使わずに!empty($a) ? $a : $b
とするのが安全ですね。
-
ここを誤解して覚えていました ↩