はじめに
初投稿です。
PHPの文字列とかの比較のキャストがよくわからない仕様だったので自分なりにまとめたものです。
バグかと思いきや仕様です
if ("3aaaaa" == 3)
{
echo "true";
}
else
{
echo "false";
}
さぁ結果はどうなったでしょう?
結果は~
ture
私は最初「は?」と思いましたが、どうやらPHPの仕様だそうです。
PHPでは文字列型と数値型など異なる型で比較を行うと文字列は数値にキャスト(変換)
されます。
この仕様のお陰で文字列をintにキャストすると
echo (int)"3aaaaaaa"; //3 と出力される
echo (int)"hoge"; //0 と出力される
echo (int)"01aaaaa"; //1 と出力される
echo (int)" 01db"; //1 と出力される
と表示されます。
これらからわかるようにキャストにもルールがあります。
キャストルール
文字列の先頭が数値ならばそこが抜き出され、
そうでなければ0になる。
なお、先頭の空白や0は無視される。
とありますが例外もあります、あります・・・。
例外
文字列が数値形式である場合
if ("3.0" == "3") {
echo "true";
}else{
echo "false";
}
結果true
if ("3e0" == "3") {
echo "true";
}else{
echo "false";
}
結果true
あれ~おかしいね~""で囲ってるから文字列のはずなんだけどな~~
これもキャストの仕様です。
キャストルール
PHPでは数値形式の文字列を比較する場合、それは整数として比較されます。
つまり、文字列型と文字列型の比較の場合においてでも、
比較対象が両方とも数値形式(数値として解釈できる文字列)場合は、
整数型としての比較になります。
因みに以下が数値として見られる文字列です
"123" ← 数字だけ
"3.0" ← 小数点
"-6" ← 負数
"0003" ← 先頭に0と数字だけ
"1e3" ← 浮動小数点数
"0x3A" ← 16進数
たくさんの0
if ( null == false) {
echo "true";
}else{
echo "false";
}
if ( 0 == "") {
echo "true";
}else{
echo "false";
}
結果 両方トモtrue
一体どこにtrue要素があるのか理解に苦しみますがこれもキャストのせいです。
なんと全部0にキャストされてるのでtrueです。
ヤバイね
対策
- 比較などをする際は必ず””(ダブルクォーテーション)で囲うなど型を意識して使う
- 例外などを除きある程度これで対策できる
- ===(イコールイコールイコール)を使う
- ===は$aが$bに等しく、および同じ型である場合にtrueとなるので型変換が行われず比較が行われる。
- 但し何も考えずすべて===を使用すると動的型付け言語であるPHPとしては少々もったいないので適材適所==と===を使い分ける。
なので===を使うと上記の0で全部処理されていたものが以下のようになります
== | null | false | “” | 0 |
---|---|---|---|---|
null | true | true | true | true |
false | true | true | true | true |
"" | true | true | true | true |
0 | true | true | true | true |
全部true
=== | null | false | “” | 0 |
---|---|---|---|---|
null | true | false | false | false |
false | false | true | false | false |
"" | false | false | true | false |
0 | false | false | false | true |
区別される
まとめ
・文字列型と数値型の比較の場合、数値型と同じ型にキャストされる
・文字列型と文字列型の比較でも、両方とも数値形式の場合、数値型へキャストされる
・”==”と”===”の機能の使い分けをする、特にnull,false,””,0の比較に関しては”==”だと全てキャストされ”0”として認識され比較がすべてtrueになるので注意
-”===”を使いキャストせずに比較する事。