目次に戻る
NULLと未定義
NULL型
NULL という型があります。PHPでは null
と書きます。大文字小文字は区別されません。以下のコードを実行してみましょう。
<?php
$var = null;
var_dump($var);
NULL
TRUE
FALSE
NULL
をまとめて 三値 と呼ぶことがありますが、これらを漢字一文字で表すと
-
TRUE
… 真 -
FALSE
… 偽 NULL
… 無
として解釈されます。命題「今日は学校に行く日か?」で例えると、
-
TRUE
…今日は学校に行く日である -
FALSE
… 今日は休みの日である NULL
… そもそも中退してた
のようなイメージです。
未定義(Undefined)
NULL
は 無 と言いながらも…
PHPコード<?php $var = null; var_dump($var);
確かにこの例では変数 $var
は値 NULL
を持つものとして存在していました。ここで別の例を考えてみましょう。
<?php
var_dump($var);
PHP Notice: Undefined variable: var in ...
NULL
「変数varが未定義だよ!」 という Notice を発生しながらも、何故か NULL
と表示されていますね。PHPでは、未定義の値を取得しようとしたときに、Noticeを発生しながら NULL
を代わりに取得します。
また、配列において未定義のキーから値を取得しようとしたときにも、エラーメッセージは微妙に違いますが同様のNoticeが発生します。
<?php
$var = array('A', 'B');
var_dump($var[2], $var['foo']);
PHP Notice: Undefined offset: 2 in ...
NULL
PHP Notice: Undefined index: foo in ...
NULL
PHPプログラマは、
- Noticeを気にせずに手抜きコーディングをする人
- Noticeの発生に気を付けて丁寧にコーディングする人
に大分されると思いますが、もちろんここでは後者を目指してコーディングを行っていきます。Noticeが発生するだけで処理速度が大幅に低下するので、これを潰すメリットはかなり大きいです。
Noticeを出さずに未定義をチェックする方法
ここからは少し復習も入ります。
【PHP入門講座】 想定外の入力への対応
http://qiita.com/mpyw/items/f298828002bbc488fe89
こちらで既に少し触れていますが、 isset
構文を用いる方法があります。 isset
は関数ではなく言語構文であるが故に、未定義の変数から値を取得しようとしてもNoticeを発生しないという強力な特長を持っています。
isset
が真を返す条件
通常の変数
- 変数が 定義 されている
- 且つ、
NULL
以外 の値を取る
<?php
$v2 = null;
$v3 = false;
var_dump(isset($v1), isset($v2), isset($v3));
bool(false)
bool(false)
bool(true)
配列のキー
- キーが 定義 されている
- 且つ、
NULL
以外 の値を取る
<?php
$v = array();
$v[1] = null;
$v[2] = false;
var_dump(isset($v[0]), isset($v[1]), isset($v[2]));
bool(false)
bool(false)
bool(true)
NULL
と未定義を区別する方法
まず真っ先に思いつくのは、値を取得しようとしてみてエラーが発生したかどうかをチェックする、という方法でしょう。しかし、これにはいろいろ制約が多く、現実的な方法ではありません。そこで別の方法を考えてみましょう。
配列におけるキーが存在するかどうか
array_key_exists
関数を利用します。これは、キーが定義されているときに必ず TRUE
を返します。 NULL
でも TRUE
となります。これが isset
構文との大きな違いです。
array_key_exists
http://php.net/manual/ja/function.array-key-exists.php
<?php
$v = array();
$v[1] = null;
$v[2] = false;
var_dump(
array_key_exists(0, $v),
array_key_exists(1, $v),
array_key_exists(2, $v)
);
bool(false)
bool(true)
bool(true)
グローバル空間における変数が存在するかどうか
グローバル空間 とは、関数内ではない、要するに 一番外側の空間 を指します。今まで扱ってきた場所はほとんどグローバル空間です。グローバル空間にある変数は グローバル変数 といいます。
PHPでは、グローバル空間にある変数を スーパーグローバル変数 $GLOBALS
で配列として取得することが出来ます。スーパーグローバル変数に関しては後で詳しく学習するので、ここでは軽く流してください。
<?php
$v2 = null;
$v3 = false;
var_dump(
array_key_exists('v1', $GLOBALS),
array_key_exists('v2', $GLOBALS),
array_key_exists('v3', $GLOBALS)
);
bool(false)
bool(true)
bool(true)
関数内における変数が存在するかどうか
グローバル空間では変数 $GLOBALS
が用意されていましたが、関数内では get_defined_vars
関数の返り値を利用します。
get_defined_vars
http://php.net/manual/ja/function.get-defined-vars.php
<?php
function test() {
$v2 = null;
$v3 = false;
var_dump(
array_key_exists('v1', get_defined_vars()),
array_key_exists('v2', get_defined_vars()),
array_key_exists('v3', get_defined_vars())
);
}
test();
bool(false)
bool(true)
bool(true)
NULL
と未定義を区別しようと思うな!!!
いろいろやってきましたが、正直 面倒くさい ですよね。普通に配列をチェックするだけなら素直に array_key_exists
を使えばいいような気もしますが、動作速度は isset
の方が速いです。
【結論】 NULL
と未定義の区別が必要なデータ構造は設計を誤っている。