Help us understand the problem. What is going on with this article?

PHPのissetと!is_nullは違うという話

はじめに

こんにちは、普段は業務で求人系サービスの開発や社内向けツールの開発を行なっている@taku-0728です。
今回はPHPの存在チェックによく使われるissetと、その逆として取り上げられるis_nullの違いについて取り上げます。公式ドキュメントの型の比較表などではissetis_nullの結果は正反対で記載されているのでisset = !is_nullだと思う方もいるかもしれませんが、実はこの2つには違いがあります。
知っている人からしたら当たり前かもしれませんが、比較表だけみたら同じように思えるので、詳細を調べたことがない方は参考にしてもらえればと思います。

結論

細かいことはいいから先に結論が知りたい人向けに結論をまとめます。
isset!is_nullで違いがあるのは下記です。

  • 未定義の変数を比較した場合
  • 実行速度

以下で順番に解説していきます。

解説

未定義の変数を比較した場合

test1.php
<?php

$x = 'test';

var_dump(isset($y));
?>

上記のコードの実行結果は下記のようになります。

bool(false)

それに対し、下記のコードはどうなるでしょうか

test2.php
<?php

$x = 'test';

var_dump(!is_null($y));
?>

答えはこうなります。

PHP Notice:  Undefined variable: y in test2.php on line 5

issetでは未定義の変数を比較してもエラーになりませんが、!is_nullだとエラーになります。
なぜこのようになるか解説していきます。

isset

isset — 変数が宣言されていること、そして NULL とは異なることを検査する

公式ドキュメントより
issetは変数が宣言されていることと、NULLではないことを検査するので、実行結果はfalseになります。

is_null

is_null — 変数が NULL かどうか調べる

公式ドキュメントより
is_nullは変数がNULLかどうかを調べるのみであり、issetとは違って変数が宣言されてるかどうかは検査してくれません。そのため結果はissetとは異なります。

公式ドキュメントの解説を読んでいただければもう解説する必要はないと思いますが、issetは変数が宣言されていることを確認してくれますが、is_nullはNULLかどうかしか確認してくれません。そのため未定義の変数を比較すると差が生まれるというわけです。

実行速度

isset!is_nullの実行速度に違いがあるのか1000万回比較して検証してみます。

<?php
$check_data = "";

// isset
$start_time1 = microtime(true);
$sum = 0;
for ($i=0; $i<=100000000;$i++) {
    if (isset($check_data)) {
      $sum += $i;
    }
}
$end_time1 = microtime(true);
var_dump('isset処理時間:'.($end_time1 - $start_time1)."秒\n");


// is_null
$start_time2 = microtime(true);
$sum = 0;
for ($i=0; $i<=100000000;$i++) {
    if (!is_null($check_data)) {
      $sum += $i;
    }
}
$end_time2 = microtime(true);
var_dump('!is_null処理時間:'.($end_time2 - $start_time2)."秒\n");
?>

3回実行してみましたが、実行結果は過去のようになりました。

string(37) "isset処理時間:1.1999080181122秒
"
string(39) "!is_null処理時間:1.6563079357147秒
"
string(37) "isset処理時間:1.2162489891052秒
"
string(39) "!is_null処理時間:1.6646618843079秒
"
string(37) "isset処理時間:1.1731791496277秒
"
string(38) "!is_null処理時間:1.658478975296秒
"

2つの処理時間には大体0.4~0.5秒ほどの差があることがわかります。
今回は条件式の中でカウンタ変数の加算をしているだけなので大した差にはなっていませんが、
条件式の中が複雑になるほど処理時間に差は生まれると思います。

(追記 コメントにてご指摘をいただきましたが、誤った理解でしたので訂正しておきます)
では同じようなことをやっているのになぜ差が生まれるのでしょうか?

言語構造と関数の違い

isset!is_nullの処理速度に違いが生まれる理由はissetがPHPの言語構造であり、is_nullは関数だからです。
言語構造とはその名の通り、言語を構成する要素のことです。関数のように定義して使うものではなく、すでにPHPの中に組み込まれた機能のことです。
PHPの言語構造一覧についてはこちらの公式ドキュメントを参照ください。
言語構造はPHPの中にすでに組み込まれているので、関数より先に確認にいきます。だから関数であるis_nullよりも、言語構造であるissetで比較する方が処理速度が早くなるわけです。
また、issetは言語構造であるが故に未定義の変数から値を取得しようとしてもエラーにはなりませんが、is_nullは関数であるため未定義の変数から値を取得しようとするとエラーになるわけです。

まとめ

PHPのisset!is_nullには

  • 未定義の変数を比較した場合
  • 実行速度

の2つに違いがあります。その理由はissetがPHPに予め組み込まれた言語構造であるのに対し、is_nullは関数だからです。
基本的に変数の存在チェックにはissetを使えば問題ないとは思いますがissetis_nullは必要と用途に応じて使い分けた方がいいと思いますが、issetは空文字''をtrueとしてしまうので値が入っているかどうかを比較する際にはお気をつけください。
また、!is_null!== nullと等価ですのでこちらも好みに合わせて使い分けてください。

参考

taku-0728
2018年新卒入社のエンジニアです。 PHPでLaravel使って求人系サービスや、社内向けツールの開発してます。
dip-net
ディップ株式会社は「バイトル」「はたらこねっと」などの求人情報サービスをはじめ、人工知能専門メディア「AINOW」、スタートアップ専門メディア「スタートアップタイムズ」、アニメなどの舞台を紹介するサイト「聖地巡礼マップ」といった新しい分野のサービスを自社で開発・運営しています。
https://www.dip-net.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away