PHPをやっていると、必ずNULLや空文字のチェックで躓くので(少なくとも自分は、、、)、何度も同じ過ちを繰り返さないようにメモしておきます。
この記事の内容
- イコール2つ(==)でNULLチェックや空文字チェックがうまくいかないのはなぜ?
- 「==」は比較対象の型チェックを行わない
- 「===」は比較対象の型チェックを行う
- 「==」は値の比較をする前に、型をそろえる処理が事前に走る
- 数値文字は数値に変換
- PHPでは nullもfalseも空文字も0も値としては同じ(型は違う)!!
経緯
以前PHPでプログラムを書いている時にハマったこと。
例えば、変数$varに「0」が入ってくる場合、NULLチェックと空文字チェックをしたのですが、予期せぬ判定がされました。
$var = 0;
if($var == '') { 内部処理が実行されてしまう } // ケース1
if($var == NULL) { 内部処理が実行されてしまう } // ケース2
if(empty($var)) { 内部処理が実行されてしまう } // ケース3
自分としては$varの中身が「0」だから空欄でもNULLでもない認識で、もちろんif文の中には入らないと思っていました。しかしケース1~3では内部処理が実行されてしまいます。
他にもいろいろ試してみた結果、逆に以下のようなケースではif文は内部処理されない!?
$var = 0;
if($var === '') { 内部処理が実行されない } // ケース4
if($var === NULL) { 内部処理が実行されない } // ケース5
if(is_null($var)) { 内部処理が実行されない } // ケース6
なんでぇ?
解説
NULLもFALSEも空文字も0も、値は同じ
まずケース1とケース2について解説します。
自分が根本的に勘違いしていたのが、PHPでは NULLもFALSEも空文字も0もすべて同じ値として認識して扱うということです(^^;。
そのためif(0 == NULL)も、if(0 == '')も、if(false == null)も全部判定結果はTRUEとなり、1と2のケースでは内部処理されてしまいます。
次にケース3です。
empty関数は、変数が空であるかどうかを検査する関数です。
ここで言う空とは、単に空文字のことではなく以下のものを指すそうです。
空とは
- "" (空文字列)
- 0 (整数 の 0)
- 0.0 (浮動小数点数の 0)
- "0" (文字列 の 0)
- NULL
- FALSE
- array() (空の配列)
よって、empty関数では$varが仮に0だろうと空文字だろうNULLだろうと、同じものとして判別してしまいます。
値比較(==)と型比較(===)
では、なぜケース4~6は0やNULLを区別することができたのでしょうか。
それはif文の条件の「==」と「===」との違いが重要なポイントとなります。
「==」は比較される両者の値が同じどうかのみチェックするのに対し、「===」では両者の値の比較に加えて、同じ型かどうかも比較します。
つまり、PHPでは0も空文字もNULLも同じ値として扱われますが、0はint型、FALSEはboolean型、nullはNULL型とそれぞれデータ型異がなるため、「==」で比較しても同じ値として判別され区別できないのに対し、「===」は区別することができたのです。
※因みに、is_null()は比較対象がNULLかどうかをチェックする関数で、$var===NULLと同じ結果を返します。
説明が分かりずらい可能性も加味して、早見表を作ってみました!
値 | if($var) | isset | empty | is_null |
---|---|---|---|---|
$var=1 | TRUE | TRUE | FALSE | FALSE |
$var=""; | FALSE | TRUE | TRUE | FALSE |
$var="0"; | FALSE | TRUE | TRUE | FALSE |
$var=0; | FALSE | TRUE | TRUE | FALSE |
$var=NULL; | FALSE | FALSE | TRUE | TRUE |
$var (初期化なし) | FALSE | FALSE | TRUE | TRUE |
$var=array() | FALSE | TRUE | TRUE | FALSE |
$var=array(1) | TRUE | TRUE | FALSE | FALSE |
下記のサイトを参考にさせて頂きました。