PHP の if, isset, is_null, empty, ?:, ??, ??= 比較表

はじめに

実務でよく使う if 文、isset、is_null、empty、エルビス演算子、Null 合体演算子、Null 合体代入演算子を比較した早見表と、動作の癖をまとめた情報を記事にしました。Web 開発の初心者、初学者の方にもわかりやすいように、ソースコードを編集してサンプルを公開しています、ご参考になれば幸いです。

検証環境

サンプル

解説

各関数と言語構造の検証結果から下記のような比較表を作成しました。

比較表だけドォーン!と見せられても理解できないと思うので、動作の癖を説明していきますね。

if 文

if 文は、 の評価によって処理を分岐させたい時に用いる基本的な構文です。

評価が false になる条件は、下記のような boolean への変換 と同じです。

(bool)'';        // bool(false)
(bool)'0';       // bool(false)
(bool)1;         // bool(true)
(bool)-2;        // bool(true)
(bool)'foo';     // bool(true)
(bool)2.3e5;     // bool(true)
(bool)array(12); // bool(true)
(bool)array();   // bool(false)
(bool)'false';   // bool(true)

if 文は、数の正負に関わらず true と評価することに気を付けましょう。

if (1)  // bool(true)
if (-1) // bool(true)

isset

isset は、変数が宣言されている、且つ null でないことを検証する言語構造です。

下記のように unset で変数の割当を解除した場合も false を返します。

$a = 1;
$b = 1;
unset($b);

isset($a); // bool(true)
isset($b); // bool(false)

第二引数は 可変長引数 になっています。複数のパラメーターを渡した場合、左から右へ評価されて、セットされていない値に出会うと評価が止まります。

$a = 1;
$b = 1;
$c = 1;
$d = 1;
unset($c);

isset($a, $b, $c, $d); // bool(false)
isset($a, $b, $d);     // bool(true)

isset は、変数を渡す必要があるので、直接値を渡したり、定数を渡すと致命的なエラーが発生するので気を付けましょう。定数の存在チェックには defined を使うと良いです。

const A = 1;

isset(1); // Fatal error: Cannot use isset() on the result of an expression (you can use "null !== expression" instead)
isset(A); // Fatal error: Cannot use isset() on the result of an expression (you can use "null !== expression" instead)

また、変数が宣言されているにも関わらず、null が代入されている場合に false を返します。不具合になりやすいので気を付けましょう。

$a = null;
$b = null;
unset($b);

isset($a); // bool(false)
isset($b); // bool(false)

is_null

is_null は、変数が null かどうかを検証する関数です。

下記 2 つは同じ意味です。

is_null($x);
$x === null;

=== null と違うところは、処理速度に微妙な差があります。100 万回試行して平均処理速度を計測したところ、下記のように is_null が少しだけ速いという結果が出ました。

is_null($x); // 1.4017022000021977E-7 秒
$x === null; // 1.4047748300005522E-7 秒

empty

empty は、変数が空であるかどうかを検証する言語構造です。

変数が未定義、又は 型の相互変換 により変数の値が false に等しい場合に、空であると見做します。つまり、下記 3 つは同じ意味になります。

empty($x);
!isset($var) || $x == false;
!isset($var) || !$x;

[], false, 0, 0.0, '', '0' と広い範囲を空であると見做すので、フォームデータのバリデーションなどに使用されている場合は気を付けましょう。

empty(''); // bool(true)
empty(0);  // bool(true)

エルビス演算子

エルビス演算子(Elvis operator)は、三項演算子 の糖衣構文(シンタックスシュガー)です。

三項演算子は if 文と同様に == で比較します。また、三項演算子は式なので、値としては評価されずに式の結果として評価されます。

因みに、エルビスという名前の由来は、アメリカのミュージシャンであるエルヴィス・プレスリーの顔文字に形が似ているところからきています。? がリーゼントで、: が目を表しています。

下記 2 つは同じ意味です。

$a ?: $b;
$a ? $a : $b;

括弧で囲わずに複数の三項演算子を使用した場合、PHP 8.0 以降では Fatal error(致命的なエラー)、PHP 7.4 以降 8.0 未満では Deprecated(非推奨)が発生するので気を付けましょう。

true ? 'true' : false ? 't' : 'f';   // PHP 8.0 Fatal error: Unparenthesized `a ? b : c ? d : e` is not supported.
true ? 'true' : false ? 't' : 'f';   // PHP 7.4 Deprecated: Unparenthesized `a ? b : c ? d : e` is not supported.
(true ? 'true' : false) ? 't' : 'f'; // t
false ? 'true' : (true ? 't' : 'f'); // t

これは、他の殆どのプログラミング言語が右から左に評価していることに対して、PHP が左から右に評価していることへの対策と思われます。

Null 合体演算子

null 合体演算子Null Coalescing Operator)は、三項演算子と isset の糖衣構文(シンタックスシュガー)です。PHP 7.0 の 新機能 として導入されました。

左辺の第 1 オペランドの値が null でない場合は、第 1 オペランドの値を返します。第 1 オペランドの値が null の場合は、右辺の第 2 オペランドの値を返します。

isset と同様に、第 1 オペランドの値が存在しない場合でも Notice や Warning が発生しません。また、null 合体演算子 は式なので、変数としては評価されずに式の結果として評価されます。

下記 2 つは同じ意味です。

$name = $_POST['name'] ?? '';
if (isset($_POST['name'])) {
  $name = $_POST['name'];
} else {
  $name = '';
}

リクエストパラメーターの受け取りなどに重宝します。

未定義の配列要素を指定しても、下記のように Notice: Undefined index が発生しないので、エラー回避に便利です。

$a = ['a', 'b'];
$b = $a[2] ?? ''; // string(0) ""

null 合体演算子は、ネストさせることもできます。

$a = null;
$b = null;
$c = false;
$d = true;

$a ?? $b ?? $c ?? $d; // bool(false)

Null 合体代入演算子

null 合体代入演算子(Null Coalescing Assignment Operator)は、null 合体演算子をさらに省略した式です。PHP 7.4 の 新機能 として導入されました。

左辺の第 1 オペランドの値が null でない場合は、何も行いません。第 1 オペランドの値が null の場合は、右辺の第 2 オペランドの値を割り当てます。

下記 4 つは同じ意味です。

$a ??= $b;
$a = $a ?? $b;
$a = @$a ?: $b;
if (!isset($a)) $a = $b;

まとめ

各関数と言語構造の癖を理解して、場合に応じて柔軟に使い分ければ OK です。

例えば、null 合体演算子は $_GET, $_POST の受け取りに便利です。empty は、広い範囲を空と判定してしまうので、できるだけ使いたくありません。エルビス演算子は、VIew 側で値によって出力する文字列を分岐させたい時に便利です。

以上です。

おわりに

サンプルのソースコードを再利用する際は、要件定義やコーディング規約にお気を付けください。