空値
以下に示されるものは全て if ($var) { ... }
のように用いたとき false
と評価されます。これらは俗に 空値 と呼ばれる値です。
名称 | 具体例 |
---|---|
数値のゼロ |
0 0.0
|
文字列のゼロ | "0" |
空文字列 | "" |
空配列 |
[] array()
|
偽 | false |
ヌル | null |
空要素から成るSimpleXMLElement |
new SimpleXMLElement('<foo></foo>') |
※ 未定義の変数は Notice: Undefined variable
を発生しながら null
として扱われます。
複雑な表を書き並べている記事が多いですが、実際は
-
null
であれば -
null
でなければ - 空値であれば
- 空値でなければ
の4種類の内容しか取り扱っていないものがほとんどであり、覚えるのが難しいなどと悩む必要はありません。至ってシンプルです。但し、(空配列はまだ分かるとして) 文字列のゼロと空要素から成るSimpleXMLElementの扱いには特に注意してください。これはPHPにおいて直感的ではない、最もクセのある実装のひとつです。JavaScriptなどと比較してもこれらの点だけ異なっていたりします。
変数の存在を確認するショートコード
これから紹介するissetやemptyは、未定義とnull
を区別することが出来ません。issetやemptyについて紹介する前に、純粋に**「変数が定義されているか」**だけをチェックする方法を紹介します。compactという関数を用います。
$a = 'hoge';
$b = 1;
$d = null;
var_dump(compact('a', 'b', 'c', 'd'));
/*
array(3) {
["a"]=>
string(4) "hoge"
["b"]=>
int(1)
["d"]=>
NULL
}
*/
この関数は現在のスコープに変数が存在している場合のみ、変数名をキーとして値を配列に取り込む動作をします。これを利用すれば、定義済みかどうかを以下のように確認することが出来ます。上記の表で紹介した**「空配列以外の配列は true
として扱われる」**という性質を利用しています。
if (compact('var')) { ... }
if (!compact('var')) { ... }
isset, !empty, !is_null の比較
上記のコードを用いると、これら3つは以下のように表現することが出来ます。
if (compact('var') && $var !== null) { ... }
if (compact('var') && $var) { ... }
if ($var !== null) { ... }
以下の原則が挙げられます。
-
issetは変数の存在をチェックするためのオーバーヘッドがあるので、定義済みであると確定している場合は
$var !== null
によるチェックで済ませるほうが良い。(但し複数同時にチェックする際に簡略化出来る場合を除く) - !emptyは変数の存在をチェックするためのオーバーヘッドがあるので、定義済みであると確定している場合は
$var
によるチェックで済ませるほうが良い。(但しempty
という語のわかりやすさから,配列が空かどうか調べるときには定義済みが確定していてもこれが用いられる場合がある) - !is_nullは関数呼び出しのオーバーヘッドがあるので、この用途では使う必要が全くない。
issetの特徴
- これは関数では無く言語構造であるため、関数ほどオーバーヘッドが大きくありません。
- 変数が未定義の場合でもエラーを出さずに
null
の確認ができます。 - 変数のみを引数として受け取ります。つまり、関数の返り値や値リテラルを直接渡すことは不可能となります。一時的に変数に代入する必要があります。
if (isset(my_example_function($arg))) { ... }
- 複数の変数を同時にチェックすることが出来ます。以下の記述はそれぞれ各行が等価になります。
if (isset($a, $b, $c)) { ... }
if (isset($a) && isset($b) && isset($c)) { ... }
if (!isset($a, $b, $c)) { ... }
if (!isset($a) || !isset($b) || !isset($c)) { ... }
- 配列キーやオブジェクトプロパティに対しても使用することができ、その場合は再帰的に未定義チェックを行ってくれます。一階層ずつチェックする必要がなくなります。
if (isset($response->errors[0]->message)) { /* TwitterAPIでよくあるエラーチェック */ }
- 文字列のオフセットをチェックすることにも使えます。以下の各行は等価です。但し、**罠が多い**ので注意が必要です。
if (strlen($buf) >= 5) { ... }
if (isset($buf[4])) { ... }
empty の特徴
- これは関数では無く言語構造であるため、関数ほどオーバーヘッドが大きくありません。
- 変数が未定義の場合でもエラーを出さずに空値の確認ができます。
- issetとは異なり、PHP5.5以降では関数の返り値や値リテラルを直接渡すことが出来ます。但し、PHP5.4以前では変数のみを引数として受け取ります。
- issetとは異なり、複数を同時にチェックすることは出来ません。
- 配列キーやオブジェクトプロパティに対しても使用することができ、その場合は再帰的に未定義チェックを行ってくれます。一階層ずつチェックする必要がなくなります。
is_null の特徴
- コールバック関数として利用することが出来ます。
$num_of_null = count(array_filter($array, 'is_null'));
array_key_exists, property_exists の利用
issetには少々汚いやり方をしないと未定義とnull
を区別できない問題がありましたが、配列やオブジェクトにおいてはそれを可能にする専用関数が用意されています。但し、引数の順序に注意してください。
if (array_key_exists('key', $array)) { ... }
if (property_exists($object, 'property')) { ... }
個人的用途まとめ
- **$_GET, $_POSTなどを受け取る際の処理**でも紹介しているfilter_inputを用いれば、issetやemptyのように存在を判定する言語構造が必要になるシーンはかなり減少する。
- 文字列が格納される可能性のある変数に関してemptyを使用するのは控える。
"0"
の扱いに問題があるためである。 - 文字列のオフセットに対してissetを用いる際はPHPバージョンに気を付ける。古いバージョンでは避けたほうが無難。