最近は業務でPHPを触っている毎日です。暗黙の型変換等々に苦しめられながら頑張っています。
今回はrange()
にやられました。
range()
とは
array range ( mixed $start , mixed $end [, number $step = 1 ] )
ある範囲の整数を有する配列を作成します。
よくある関数です。
始めの値と終わりの値とステップ数を指定して、それにあった配列を返してくれます。
foreach()
と組み合わせて使ったりするナイスガイです。
何が起きたのか
次のようなサンプルがあったとして、実行してみます。
foreach(range(1, 16, 2) as $index)
{
$logger->info('range index: ' . $index);
}
$logger->info('range array count: ' . count(range(1, 16, 2)));
$logger->info('range array 0: ' . range(1, 16, 2)[0]);
[2018-06-29 11:51:24] app.INFO: range index: 1 [] []
[2018-06-29 11:51:24] app.INFO: range index: 3 [] []
[2018-06-29 11:51:24] app.INFO: range index: 5 [] []
[2018-06-29 11:51:24] app.INFO: range index: 7 [] []
[2018-06-29 11:51:24] app.INFO: range index: 9 [] []
[2018-06-29 11:51:24] app.INFO: range index: 11 [] []
[2018-06-29 11:51:24] app.INFO: range index: 13 [] []
[2018-06-29 11:51:24] app.INFO: range index: 15 [] []
[2018-06-29 11:51:24] app.INFO: range array count: 8 [] []
[2018-06-29 11:51:24] app.INFO: range array 0: 1 [] []
期待通りの結果ですね。素晴らしいです。
では次のサンプルはどうでしょうか。
foreach(range(8, 10, 3) as $index)
{
$logger->info('range index: ' . $index);
}
$logger->info('range array count: ' . count(range(8, 10, 3)));
$logger->info('range array 0: ' . range(8, 10, 3)[0]);
[2018-06-29 11:55:09] app.INFO: range array count: 1 [] []
[2018-06-29 11:55:09] app.INFO: range array 0: [] []
……えっ。なにこれ。
count()
が1
ということは値は返ってきているのでしょうか。
いえいえrange(8, 10, 3)[0]
の結果が空なので、そもそもうまく動いている感じがしません。
ちょっといろいろ調べてみましょう。
調査
単一の値の配列の場合、そもそもforeach()
はループしてくれるのでしょうか。
foreach([8] as $index)
{
$logger->info('range index: ' . $index);
}
$logger->info('range array count: ' . count([8]));
$logger->info('range array 0: ' . [8][0]);
[2018-06-29 12:07:48] app.INFO: range index: 8 [] []
[2018-06-29 12:07:48] app.INFO: range array count: 1 [] []
[2018-06-29 12:07:48] app.INFO: range array 0: 8 [] []
ループしてくれますね。ということはsample2.php
はやはり値が返ってない感じがします。
ちょっとrange()
の値を変えて試してみましょう。
開始と終わりの数を同じにしてみます。
foreach(range(8, 8, 1) as $index)
{
$logger->info('range index: ' . $index);
}
$logger->info('range array count: ' . count(range(8, 8, 1)));
$logger->info('range array 0: ' . range(8, 8, 1)[0]);
[2018-06-29 12:09:32] app.INFO: range index: 8 [] []
[2018-06-29 12:09:32] app.INFO: range array count: 1 [] []
[2018-06-29 12:09:32] app.INFO: range array 0: 8 [] []
これは問題ありませんね。
では次。終わりを9
に、ステップ数を2
に変えます。
foreach(range(8, 9, 2) as $index)
{
$logger->info('range index: ' . $index);
}
$logger->info('range array count: ' . count(range(8, 9, 2)));
$logger->info('range array 0: ' . range(8, 9, 2)[0]);
[2018-06-29 12:14:55] app.INFO: range array count: 1 [] []
[2018-06-29 12:14:55] app.INFO: range array 0: [] []
発生しましたね。
次は終わりを8
に変えてみましょう。
foreach(range(8, 8, 2) as $index)
{
$logger->info('range index: ' . $index);
}
$logger->info('range array count: ' . count(range(8, 8, 2)));
$logger->info('range array 0: ' . range(8, 8, 2)[0]);
[2018-06-29 12:18:20] app.INFO: range index: 8 [] []
[2018-06-29 12:18:20] app.INFO: range array count: 1 [] []
[2018-06-29 12:18:20] app.INFO: range array 0: 8 [] []
発生しません。なんとなく発生する条件がわかってきました。
結果
どうやら、次の条件を満たしているとrange()
がうまく働かなさそうなことがわかりました。
array range ( mixed $start , mixed $end [, number $step = 1 ] )
- $end > $start
- $start + $step > $end
PHP5.6で試したので、もしかしたら7だと解決しているのかもしれません。
ちょっとこれでひどい目にあったので、共有まで。