📖

【Q&A】empty()の仕様が曖昧で使いにくい?

2023/02/13に公開

質問

empty() の判定が曖昧で使いにくいです。
↓以下で truefalse になる基準が理解できません。
https://3v4l.org/FPuOD

回答

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;
}
脚注
  1. PHPでしかプログラムの経験がないと、あまり違和感はないかもしれません。PHPでは数値と数字の区別がないからです。これは、HTTPプロトコル($_GET$_POST)では、『型』を送れないので、すべて文字列として送信されるからです。数値の0同様に、truefalsenullも文字列としてしか送れません。 ↩︎

  2. https://www.tohoho-web.com/php/types.html#zerovalue ↩︎

  3. JavaScript の '0' が true になるのは、文字列型を評価する場合は、文字列の長さを計算するので、半角1文字(1byte)の長さ(量)があるので true になります。 文字列型の評価で false になるのは、空文字列('')です。 ↩︎

  4. shell スクリプトの終了ステータスは、 0 が正常で 1 が異常です。 ↩︎

  5. 言語の仕様にイライラするのは、大抵の場合、理解が足りないからです。 ↩︎

Discussion