多分PHPを使っている人からしたら基本的な内容で、特に気にならないかもしれない。
だけど、普段javaなへっぽこアプリエンジニアから見たら気持ち悪かった変数周りの話。
背景
ひょんなことからPHPを勉強することになりました
普段はアプリ開発をしていて、javaとswiftと、ときどきkotlinです
で、それらの場合、以下のように変数宣言します
String string = "string";
var string = "string"
だから、PHPでの代入もてっきり、swiftみたいな型推論だと思っていたのですが、
$int = 1;
$int = "string";
というものが通ってしまうという。まず、この時点でなんか気持ち悪い。
$test = $test === false ? "success" : -1
と、お前はbooleanなのか、stringなのか、intなのか、なんなんだと問いたくなるような1文も書けてしまう
ただ、今回はそこではなく、in_arrayについて調べていてたどりついたPHPのin_arrayは罠が多いので注意喚起が必要を読んで、調べて知った気持ち悪いなと思った比較の話
本題
以下の最後の文以外、print("true")が実行されます
if ( 0 == 0 ){ print("true"); } //当たり前
if ( 0 == 0.0 ){ print("true"); } //普通
if ( 0 == "0" ){ print("true"); } //まだ、わかる
if ( 0 == "0.0" ){ print("true"); } //まだ、わかる
if ( 0 == false ){ print("true"); } //わからないでもない
if ( 0 == null ){ print("true"); } //んー、まぁ
if ( 0 == "string" ){ print("true"); } //は?
if ( "string" == 0 ){ print("true"); } //は?
if ( 1 + "string" == 1 ){ print("true"); } //は?
if ( "1" + "string" == 1 ){ print("true"); }//は?
if ( " 01 string" == 1 ){ print("true"); } //これは通るが
if ( " 0 1 string" == 1 ){ print("false"); }//これは通らない
理由としては
PHPマニュアルのStringの中の文字列の数値への変換にあるように
数値として文字列が評価された時、結果の値と型は次のように定義されます。
文字列の中に '.' や 'e'、'E' といった文字が含まれず、 数値が integer 型の範囲内 (PHP_INT_MAX で定義されています) におさまる場合は integer として評価されます。それ以外の場合は、すべて float として評価されます。
文字列の最初の部分により値が決まります。文字列が、 有効な数値データから始まる場合、この値が使用されます。その他の場合、 値は 0 (ゼロ) となります。有効な数値データは符号(オプション)の後に、 1 つ以上の数字 (オプションとして小数点を 1 つ含む)、 オプションとして指数部が続きます。指数部は 'e' または 'E' の後に 1 つ以上の数字が続く形式です。
なお、最初のスペースは除くみたいです。
このように文字列が数値変換される場合に法則があり、有効データでない場合、0になるために発生する現象です。
なので、以下も通ります。
if ( -"1" == -1 ){ print("true"); }
$test = "string" / 100; //これも正常に動く
理屈はわかるんだけれど、凄い気持ち悪い。