PHPのemptyの挙動が不安になったのでまとめてみた。
ついでにJSの空チェックの挙動も調べた。
※ empty()を使う時は大抵!empty()(存在する)の形で使ってるので、この記事の中では全て!empty()の形で動作チェックをしています。
PHPの場合
空チェックリスト
公式マニュアルが見難いので、全て「存在する」側にまとめてみた。
PHP: PHP 型の比較表 - Manual
http://php.net/manual/ja/types.comparisons.php
動作確認
http://codepad.org/Cgl6apJa
| value | memo | gettype() | !empty() | (bool) | !! | isset() | !is_null() |
|---|---|---|---|---|---|---|---|
| true | boolean | 1 | 1 | 1 | 1 | 1 | |
| false | boolean | 0 | 0 | 0 | 1 | 1 | |
| 1 | integer | 1 | 1 | 1 | 1 | 1 | |
| 0 | integer | 0 | 0 | 0 | 1 | 1 | |
| 1.0 | double | 1 | 1 | 1 | 1 | 1 | |
| 0.0 | double | 0 | 0 | 0 | 1 | 1 | |
| '1' | string | 1 | 1 | 1 | 1 | 1 | |
| '0' | string | 0 | 0 | 0 | 1 | 1 | |
| "1" | string | 1 | 1 | 1 | 1 | 1 | |
| "0" | string | 0 | 0 | 0 | 1 | 1 | |
| '1.0' | string | 1 | 1 | 1 | 1 | 1 | |
| '0.0' | string | 1 | 1 | 1 | 1 | 1 | |
| "1.0" | string | 1 | 1 | 1 | 1 | 1 | |
| "0.0" | string | 1 | 1 | 1 | 1 | 1 | |
| '' | string | 0 | 0 | 0 | 1 | 1 | |
| "" | string | 0 | 0 | 0 | 1 | 1 | |
| array() | array | 0 | 0 | 0 | 1 | 1 | |
| null | NULL | 0 | 0 | 0 | 0 | 0 | |
| $a | 未定義の変数 | NULL | 0 | 0 (Noticeが出る) | 0 (Noticeが出る) | 0 | 0 (Noticeが出る) |
| function() {} | php 5.3 以降 | object | 1 | 1 | 1 | 1 | 1 |
まとめ
- シングルクォートとダブルクォートの判定の差はない
-
!empty()と(bool)と!!の判定はほぼ同じ-
(bool)と!!は同じ- というか、PHPの
ifの中では内部的にbool型に変換して解釈してる
- というか、PHPの
-
(bool)と!!は未定義の変数に対して使うとPHP Notice: Undefined variableで怒られる -
「文字列の0.0」はtrueになる
- 文字列の0.0をfalseで判定させる機会は少ないと思われるが、一応気にかけておくこと
-
-
isset()と!is_null()の判定はほぼ同じ-
!is_null()は未定義の変数に対して使うとPHP Notice: Undefined variableで怒られる
-
- phpで空判定をしたい時は
empty()かisset()を使うのが無難 -
isset()は「変数にnull以外の何かが入っていたらtrue」 -
empty()は「0っぽい時(長さとか)はtrue」 isset()とempty()は言語構造なのでPHP Noticeが出ない
まとめ追記
array_key_exists()も、配列の空チェックにおいて重要になので追記。
http://codepad.org/IUs7iFdD
以下の構造に対してチェックした結果
$check_list = array(
'a' => 0,
'b' => '',
'c' => null,
// 'd' => null,
);
| key | !empty() | isset() | array_key_exists() |
|---|---|---|---|
| 'a' | false | true | true |
| 'b' | false | true | true |
| 'c' | false | false | true |
| 'd' | false | false | false |
重要なのは中身がnullのkeyのisset()がfalseになることです。
keyが有る無しのチェックはキチンとarray_key_exists()を使って、中身の有る無しのチェックは!empty()かisset()を使いましょう。
Javascriptの場合
空チェックリスト
FireFox 33.0 と Chrome 38.0.2125.104 m で確認。
下の表でtoString.call()と書かれている部分は、Object.prototype.toString.call()で確認した結果。
notEmpty()は自作関数、ページの下の方で解説します。
| value | typeof | toString.call() | Boolean() | !! | notEmpty() |
|---|---|---|---|---|---|
| true | boolean | [object Boolean] | true | true | true |
| false | boolean | [object Boolean] | |||
| 1 | number | [object Number] | true | true | true |
| 0 | number | [object Number] | |||
| 1.0 | number | [object Number] | true | true | true |
| 0.0 | number | [object Number] | |||
| '1' | string | [object String] | true | true | true |
| '0' | string | [object String] | true | true | |
| "1" | string | [object String] | true | true | true |
| "0" | string | [object String] | true | true | |
| '1.0' | string | [object String] | true | true | true |
| '0.0' | string | [object String] | true | true | |
| "1.0" | string | [object String] | true | true | true |
| "0.0" | string | [object String] | true | true | |
| '' | string | [object String] | |||
| "" | string | [object String] | |||
| undefined | undefined | [object Undefined] | |||
| null | object | [object Null] | |||
| [] | object | [object Array] | true | true | |
| {} | object | [object Object] | true | true | |
| function() {} | function | [object Function] | true | true | true |
まとめ
- シングルクォートとダブルクォートの判定の差はない
-
Boolean()と!!の判定は同じ -
typeofで調べると、null、array、objectが全部objectと判定される-
Object.prototype.toString.call()で調べると、ちゃんとした型がわかる
-
- 真偽値と数値の判定はPHPと同じ
- 文字列は中に空文字以外が入ってたら全部trueになっちゃう
- 0文字列を弾きたかったら別途対応する
- 配列とオブジェクト(連想配列)は全部true
- 空配列を弾きたかったら、別途対応する
JSでPHPの!emptyっぽい挙動対応版
JSでも0文字列と空配列を弾きたかったので、作ってみた。
function notEmpty(value) {
var result;
switch (typeof value) {
case 'string':
// 文字の0を除く
result = (value && value != 0);
break;
case 'object':
// 配列の中身の数チェック
result = (value && Object.keys(value).length);
break;
default:
result = value;
}
return Boolean(result);
}
三項演算子を使った1行ver。
function notEmpty(v) {
return Boolean(
typeof v == 'string' ?
v && v != 0 :
typeof v == 'object' ?
v && Object.keys(v).length :
v
);
}
- 文字列の0対応
-
result = (value && value != 0);-
value != 0のところで文字列0をfalseにする - PHPと違って文字列0.0もfalseにするけど、むしろその方が自然な気がするので気にしないことにする
-
-
- 空配列対応
result = (value && Object.keys(value).length);-
Object.keys(value).lengthのところでオブジェクトのkeyのリストを取得して、その長さを出している- 長さが0で無ければok
- 配列もオブジェクトも
Object.keys(value).lengthで項目の数がわかる
-
Object.keys(null)はnon-objectとか言われるので、先に最初のvalueのところでfalse判定して弾いている