🔤
PHP 8.0 以降に文字列のオフセットにアクセスした際の挙動の違い
どういうやつ?
こういうやつ
$str = 'The world';
var_dump($str[0]); // string(1) "T"
結論
文字列のオフセットに数値形式の文字列を指定した場合、int
と float
で挙動が変化する。
'1'
, ' 1 '
および '0001'
など int
として扱われる定した場合は普通に int
として扱われるが、
'1.0'
および '+1.0E0'
など float
として扱われる文字列を指定した場合は TypeError
になる。
実際にやってみた
全て PHP 8.0 以降です。
$str = 'The world';
var_dump($str['1']); // string(1) "h"
var_dump($str[' 1 ']); // string(1) "h"
var_dump($str['0001']); // string(1) "h"
var_dump($str['1.0']); // Fatal error: Uncaught TypeError: Cannot access offset of type string on string
var_dump($str['+1.0E0']); // Fatal error: Uncaught TypeError: Cannot access offset of type string on string
上記のオフセットの値を文字列ではなく数値にした場合はこうなる。
$str = 'The world';
var_dump($str[1]); // string(1) "h"
var_dump($str[ 1 ]); // string(1) "h"
var_dump($str[0001]); // string(1) "h"
var_dump($str[1.0]); // string(1) "h" Warning: String offset cast occurred
var_dump($str[+1.0E0]); // string(1) "h" Warning: String offset cast occurred
単純に float
を指定する分には Warning
は出るけど TypeError
にはならない。
同じ数値形式の文字列でも挙動が変わるのは意外だった。
php-src を読んで原因を探ってみたい。
おまけ
数値から始まる文字列を指定すると別の Warning: Illegal string offset
が出る。
また文字列の長さ以上のマイナス値を指定し、そこに代入しようとしても同じ Warning
が起きる。
$str = 'The world';
var_dump($str['1str']); // string(1) "h" Warning: Illegal string offset "1str"
var_dump($str[-10] = 'foo'); // NULL Warning: Illegal string offset -10
var_dump($str); // The world
この Warning: Illegal string offset
の起こし方を研究していて今回の現象を観測したので記事にしてみました。
他にも Illegal string offset
の起こし方のパターンを知っている方がいたら教えていただけると嬉しいです。
見た資料
Discussion