【Q&A】empty()の仕様が曖昧で使いにくい?
質問
empty()
の判定が曖昧で使いにくいです。
↓以下で true
と false
になる基準が理解できません。
回答
empty()
の結果(trueになるかfalseになるか)について理解するのは、 初心者にはとても難しい です。
プログラミングに慣れてくると、empty()
の結果は合理的です。 その値が『空』と見なせる場合に、 true となります 。
PHPの前に、C言語などバイナリ(0と1のデータ)を扱うプログラムの経験がないと、直感的に理解するのは難しいと思います。お勧めは 丸暗記 です。何が true
で、何が false
か、丸暗記してしまうのが初心者には手っ取り早いと思います。
丸暗記❗empty() が true を返す変数の一覧
null
, false
, 0
, '0'
, ''
, []
これだけです。これ以外は false
になるので丸暗記しちゃいましょう。
数値の0と、数字の'0'
0
と '0'
の違いは、数値の0
か、数字の0
かの区別です。どちらも empty()
では true
になります。[1]
空文字列
''
は、空文字列を表しています。
空の配列
[]
は、空の配列です。
[[]]
は、空の配列に、さらに空の配列が入っている状態です。空の配列同士なので、 empty()
では true
が返るべきで、 false
が返るのはバグではないか?という質問がありました。
これは、空の配列に空の配列が入っているので、空ではないという事になります。(禅問答のようですね)
配列のアイテム数をカウントする count()
という関数がありますが、これで考えると分かりやすいと思います。
echo count([]); // 0
echo count([[]]); // 1
以下は、とほほのPHP入門[2]にある図を借用しました。とてもわかりやすいです。
JavaScriptとの違い
JavaScriptでは、以下は true になります。[3]
console( '0' ? true: false; );
プログラミング言語は、箱庭です。なぜそのような仕様かというと、作った人がそう決めたからです。作った人が、
1 は false だ
と決めれば、1 は false になります。[4]
プログラミング言語に整合性を求めるとイライラします。そういうものだと割り切りましょう。[5]
isset() と empty() について
よくある誤解ですが、 empty()
は、 isset()
の対になる関数ではありません。
つまり、 if( isset(変数) )
と if( !empty(変数) )
は一緒の意味ではありません。
isset()
isset()
は、変数が存在しているか(定義済か)確認する為だけの関数です。
$var = '0';
echo isset($var) ? 'true':'false'; // true。変数がセットされているので。
// データベースを更新
if( isset($var) ){
$DB->Update(['flag'=>$var]); // flagのリセット
}else{
echo 'バリデーションエラー';
}
empty()
empty()
は、 変数が存在しない ことを確認する関数ではありません。
変数の初期化に使いたい場合は、isset()
やNULL合体演算子を使います。
$user_name = $_GET['user_name']; // 空文字列('')や送信されていない場合にエラーにしたい
if( empty($user_name) ){
echo 'ユーザー名が設定されていません';
return;
}
-
PHPでしかプログラムの経験がないと、あまり違和感はないかもしれません。PHPでは数値と数字の区別がないからです。これは、HTTPプロトコル(
$_GET
や$_POST
)では、『型』を送れないので、すべて文字列として送信されるからです。数値の0
同様に、true
、false
、null
も文字列としてしか送れません。 ↩︎ -
JavaScript の '0' が
true
になるのは、文字列型を評価する場合は、文字列の長さを計算するので、半角1文字(1byte)の長さ(量)があるのでtrue
になります。 文字列型の評価でfalse
になるのは、空文字列('')です。 ↩︎ -
shell スクリプトの終了ステータスは、
0
が正常で1
が異常です。 ↩︎ -
言語の仕様にイライラするのは、大抵の場合、理解が足りないからです。 ↩︎
Discussion