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判定して弾いている