わけあって書きたくなかった PHP 関連の作業をすることになりました。なんてこった。
いままで PHP を書いて生きてこなかったんですが、まぁ Go とか Python とか他の言語の知識である程度はなんとかなるものです。
とは言っても PHP 学習歴数時間の人間の話です。
とりあえず既存プログラムの改修をしているのですが、う〜ん、どうもこれ PHP というかプログラミングを知らない人間が書いている気がする…と思ったので言語独自の解釈の確認から。(まぁ私もプログラマではないのですが)
で、まぁよくある null の確認です。
あぁ、これ見るだけで嫌になりますね。ポイントになるのは上の 4 項目でしょうか。
- 空文字
- null
- 未代入
- 未定義
似ているようで異なるこれらのパターンですが、この表を見る限り is_null()
と isset()
は真逆の解釈をするようです。つまり is_null() == !isset()
または !is_null() == isset()
という話です。
「PHP だしそんなことないよな〜」と思っていたら案の定違いがありました。
<?php var_dump($foo); var_dump(is_null($foo)); var_dump(!isset($foo));
PHP Notice: Undefined variable: foo in /tmp/sh-thd-6879852719 (deleted) on line 2 NULL PHP Notice: Undefined variable: foo in /tmp/sh-thd-6879852719 (deleted) on line 3 bool(true) bool(true)
判定は is_null()
も isset()
も同じく true
ですが、isset()
は変数が Undefined であっても E_NOTICE
を吐かないようです。
公式の説明では下記のように書いてあります。(誤字なんとかしろよ)
注意:
$xが定義されていない状態で単に if ($x)としてしまうとE_NOTICE レベルのエラーが発行てしまいます。代わりに、empty()や isset()を使うかあるいは変数を初期化するように してください。
この説明に is_null()
が含まれていないところを見ると is_null()
は E_NOTICE
を吐くのでしょう。
E_ERROR
ではないのだからいいのではないかと済ます人もいるでしょうが私はそういうのが嫌いです。きちんと対処すれば出力されないメッセージのおかげで大事なメッセージが埋もれてしまいます。インフラ的観点からしてもログファイルが肥大化するので勘弁して欲しいです。
で、上の表からするに PHP では「変数が定義済みかどうかわからない状態で厳密に $foo = null
を正確に調べる方法は is_null()
や isset()
単体では調べられないのでは?」と思った。
PHP の公式には null について下記のように書いてある。null の範囲が広すぎない?
- 定数
NULL
が代入されている場合。- まだ値が何も代入されていない場合。
unset()
されている場合。
上の説明を読むに空文字は「値」に含まれないようだ。シェルで言うところの test -n "${foo}"
レベルの判定しかしないっぽい。
SQL では厳密に null を判定する方法として is null
があったりするけど、DB と組み合わせて使う PHP の null の解釈がこれではユーザが混乱するのではないだろうか。
コーディングルールも null
や true
、false
は小文字で書けと言いつつ、定数だから大文字書くべきなのでは?と思ったり。
厳密に null かどうかを判別するのは同ページの === による厳密な比較
に書いてあるがこれだけなようだ。
$foo === null
is_null()
や isset()
などは複数のパターンで判定するのに使えるが厳密なチェックには使えない、と。
やっぱりヤダ PHP。