偉大なる先駆記事 や 公式の比較表 に感謝の念を捧げつつ、「空白スペースのみの文字列」とかNull合体演算子とかin_arrayとかもまとめたいなと思ったので書きました。
間違いへのツッコミ・補足・追記などなど、ございましたらお気軽にお投げいただけますと幸いです。
※動作確認環境:PHP 8.1.29
前程 - PHPにとっては文字列"0"もfalse
bool に変換する場合、次の値は false とみなされます。
- boolean の false
- integer の 0 (ゼロ)
- float の 0.0 および -0.0 (ゼロ)
- 空の文字列 ""、 および文字列の "0"
- 要素の数がゼロである 配列
- unit 型 NULL (値がセットされていない変数を含む)
- bool 型へキャストするように動作がオーバーロードされた内部オブジェクト。 例: 属性がない空要素から作成された SimpleXML オブジェクト。
雑な表現ですが「PHPにとっては0も"0"も""も[]もfalseもお仲間」1と思いつつ後述の表を見ると、より理解しやすくなるんじゃないかなと思います。
私はPython(とJava)しか経験したことのなかった人間なので、PHPの仕様を知った瞬間は宇宙猫になりました。23
本題1 - 存在・状態判定系の機能の違い早見表
| if($var)4 | isset($var)56 | empty($var)7 | is_null($var)8 | $var === null9 | |
|---|---|---|---|---|---|
| $var=1;10 | true | true | false | false | false |
| $var="";11 | false | true | true | false | false |
| $var=" ";12 | true | true | false | false | false |
| $var="0"; | false | true | true | false | false |
| $var=0;13 | false | true | true | false | false |
| $var=NULL; | false | false | true | true | true |
| 未定義14 | Notice15(false) | false | true | Notice(true) | Notice(false) |
| $var=[]; | false | true | true | false | false |
| $var=true; | true | true | false | false | false |
| $var=false; | false | true | true | false | false |
太字は独断と偏見による要注意箇所です。私が引っかかった箇所ともいう。
PHPにとっては数値の0も文字列の"0"も「空」なんですね。
そーなのかーって思いつつ wikipedia を覗いてみたら「0は数量が空っぽであることを意味する数である」って書かれていました。虫かごにイナゴが0匹いるのなら、その虫かごは空だよねってことかもしれません。なるほどね完全に理解したわ。
追記 - 存在・状態判定系の機能の違い早見表(否定ver)
思いのほか本記事をセルフ参照することと、否定版の表もほしいと思うことが多発したため書きました。
| if(!$var) | !isset($var) | !empty($var) | !is_null($var) | $var !== null | |
|---|---|---|---|---|---|
| $var=1; | false | false | true | true | true |
| $var=""; | true | false | false | true | true |
| $var=" "; | false | false | true | true | true |
| $var="0"; | true | false | false | true | true |
| $var=0; | true | false | false | true | true |
| $var=NULL; | true | true | false | false | false |
| 未定義 | Notice(true) | true | false | Notice(false) | Notice(false) |
| $var=[]; | true | false | false | true | true |
| $var=true; | false | false | true | true | true |
| $var=false; | true | false | false | true | true |
本題2 - その他の存在・状態判定系の機能およびNull合体演算子の違い早見表
Null合体演算子??16
|
in_array(値, $var) | in_array(値, $var, true) | method_exists($var, "メソッド名") | property_exists($var, "プロパティ名") | |
|---|---|---|---|---|---|
| true | issetと同じ17。左辺が未定義・NULL以外の場合は、左辺を返す | 指定値が $var配列 に存在する。型は不問18
|
指定型の指定値が $var配列 に存在する19
|
$varオブジェクト または クラス名文字列 に、指定メソッドが存在する |
$varオブジェクト に指定プロパティが存在する20
|
| false | issetと同じ。左辺が未定義またはNULLの場合21は、右辺を返す | 指定値が $var配列 に存在しない22
|
指定キーが $var配列 に存在しない23
|
$varオブジェクト または クラス名文字列 に、指定メソッドが存在しない |
$varオブジェクト に指定プロパティが存在しない |
他にも「定数が定義されている」ことを判定する defined とか、「変数が配列である」ことを判定する is_array とか、「変数がオブジェクトである」ことを判定する is_object とかがいるらしいです。私は使ったことないけど。
おまけ - ぼくのかんがえたさいきょうの存在判定
ある日、私は「フォーム入力・送信された値が、存在するかどうかを知りたいな」と考えました(真偽値は数値1 or 0にキャストするよう実装済み)。
私の脳内国語辞書における「値が存在する」は「NULLでも空文字でも空白スペースのみでもなく、0および"0"を含む」と書かれています。
しかしPHPにとっては違うようで、「私の考えた、存在する値」判定関数はありません。
ということで、isset($var) && trim((string)$var) !== "" という条件文を書いてみました。
ちなみに判定値は配列ではないので、配列のことは考慮していません。
| if($var) | isset($var) | empty($var) | is_null($var) | $var === null | isset($var) && trim((string)$var) !== "" |
|
|---|---|---|---|---|---|---|
| $var=1; | true | true | false | false | false | true |
| $var=""; | false | true | true | false | false | false |
| $var=" "; | true | true | false | false | false | false |
| $var="0"; | false | true | true | false | false | true |
| $var=0; | false | true | true | false | false | true |
| $var=NULL; | false | false | true | true | true | false |
| 未定義 | Notice(false) | false | true | Notice(true) | Notice(false) | false |
| $var=[]; | false | true | true | false | false | Warning24 (true) |
| $var=true; | true | true | false | false | false | true |
| $var=false; | false | true | true | false | false | false |
解決! ヨシ!
参考
余談の参考
-
雑でない表現をすると、これら「お仲間」のことを「falsy」という ↩
-
Pythonの"0" は……true(truthy)なのである……! ↩
-
余談:boolのfalseを文字列変換したら、""になる 仕様にも目を丸くした ↩
-
「1以上の値を持つ」ことを判定する。数値0・文字列"0"・空配列はfalseになる ↩
-
「変数に対するセット(空文字や空配列を含む)が行われている」こと = 「未定義・NULL以外(変数が存在し、かつNULL以外)」であることを判定する ↩
-
余談:issetの引数には変数しか渡せない。関数(の戻り値)、定数、文字列、計算式といった「変数以外」を渡すとエラーになる(参照:PHP公式リファレンス) ↩
-
「1以上の値(空白スペースのみの文字列を含む)が存在しない」ことを判定する。「
if(!$var)または 未定義」ともいえる ↩ -
「NULLである」ことを判定する。
$var === nullとほぼ同じ。結局どっちがいいんだ?と首をひねっていたが、どうやら両派閥が存在するらしい ↩ -
is_null($var)とほぼ同じだが、未定義の場合にNotice(false)になる点と、比較演算のほうが(誤差レベルで)高速な点が異なる。ってChatGPTは言っていたが、実際どのくらい高速なのか私は知らない ↩ -
$var="0.0";や$var="NULL";や$var="null";も同じ結果になる ↩ -
空の文字列 ↩
-
空白スペースのみの文字列 ↩
-
$var=0.0;も同じ結果になる。$var="0.0";は$var="0";と違う結果になるのに…… ↩ -
Notice: Undefined variable(PHPのエラーレベル「通知」)が発生する。「処理は停止されないが、バグの原因になりうるため非推奨」なコードであることを示す ↩ -
余談:ちょっと似てるけど別存在として、三項演算子
?:という子がいる。「条件 ? 条件がtrueの場合の値 : 条件がfalseの場合の値;」というふうに書く。と記しておくことで未来の私が助かる ↩ -
PHP公式リファレンス にもそう書かれている ↩
-
例えば
$var = [0]の際のin_array("0", $var)や、$var = [null]の際のin_array(null, $var)はtrueになる ↩ -
例えば
$var = [0]の際のin_array("0", $var, true)や、$var = [null]の際のin_array(null, $var, true)はfalseになる ↩ -
指定プロパティの格納値は不問。つまり指定プロパティの値が0でも"0"でも""でもnullでもtrueを返す ↩
-
!isset($var)の場合ともいう ↩ -
$varが空配列である場合はtrueになる。「指定値が
$var配列に存在しない」なので ↩ -
もちろん、$varが空配列である場合はtrueになる ↩
-
Warning: Array to string conversion(PHPのエラーレベル「警告」)が発生する。「処理は停止されないがバグの原因になりうるため、Noticeより重いレベルの非推奨」なコードであることを示す。ちなみに配列をstringにキャストすると、文字列"Array"に変換される(要素は無視される) ↩