PHPの文字列に対するisset
んー.PHPを6-7年近く使ってきたけど,初めて知った.
<?php $string = "hogehoge"; var_dump(isset($string["arienai"])); ?>
の結果は,trueです.
PHP :: Bug #44587 :: Problems whene asking if a key of an array isset, and the variable is not arrayにもあったけど,PHP5.2.0で試しても同じだったから,ずっと昔からの仕様なのかなぁ.ううーん.怖いな.
よく考えたらそんなに変な挙動じゃないのか.
文字列の最初の部分により値が決まります。文字列が、 有効な数値データから始まる場合、この値が使用されます。その他の場合、 値は 0 (ゼロ) となります。有効な数値データは符号(オプション)の後に、 1 つ以上の数字 (オプションとして小数点を 1 つ含む)、 オプションとして指数部が続きます。指数部は 'e' または 'E' の後に 1 つ以上の数字が続く形式です。
PHP: 文字列 - Manual
とあって,PHPでは,
<?php $string = "hogehoge"; var_dump($string[0]); ?>
は,stringの0番目の文字だから"h"と表示される.で,先ほどの
<?php $string = "hogehoge"; var_dump(isset($string["arienai"])); ?>
は,文字列stringの"arienai"番目の文字で,"arienai"という文字列は整数に変換されて,$string[0]を参照することになる.
なぜこんなことで引っかかったかというと,文字列が入ってくるか配列が入ってくるかわからない関数で
<?php function test($data){ if(isset($data["pattern"]){ return '/' . $data["pattern"] . '/'; }else{ return '/' . $data . '/'; } } test('mogemoge'); //"/m/" test(array("pattern" => "mogemoge")); //"/mogemoge/" ?>
とかなってて,正しくは
<?php function test($data){ if(is_array($data) && isset($data["pattern"]){ return '/' . $data["pattern"] . '/'; }else if(is_string($data)){ return '/' . $data . '/'; }else{ throw new Exception("illegal argument"); } } test('mogemoge'); //"/mogemoge/" test(array("pattern" => "mogemoge")); //"/mogemoge/" ?>
としないといけないと.型あるじゃん!はいいっこなし.