PHP で array_reverse() を使うときの注意点

先日 PHP の array_reverse() 関数を使っていて驚いたことがあったので備忘録として残しておきたいと思います。

array_reverse() は要素の順番を前後逆にした配列を返してくれる関数です。使用例はこちら。

インデックス配列:

$original = [5, 9, 6, 3];
array_reverse($original);
// => [3, 6, 9, 5]

連想配列:

$original = ['orange' => 2, 'apple' => 5];
array_reverse($original);
// => ['apple' => 5, 'orange' => 2]

いずれも直感的で自然なふるまいです。

注意すべきなのは要素数が 1 の連想配列の場合です。例えば次の場合。

$original = [1000 => 'car'];
array_reverse($original);
// => ['car']

array_reverse() をかけると、オリジナルの配列にあったキー 1000 がどこかに行ってしまいました。

これは利用側の問題でもあり「まぁ仕方ないかなぁ」とも思えますが、厄介なのは一見インデックス配列ではない配列の場合です。

キーが数字に変換できる文字列の場合:

array_reverse(['1998' => 'car'])
// => ["car"]

これだと意図せずキーが数字とみなしうる場合に思わぬふるまいを招きます。

このふるまいは一応仕様とのことで・・・ array_reverse() の第 2 引数に TRUE を渡せば回避することができます。 ドキュメントで関数の宣言部を確認すると次のようになっています。

array array_reverse ( array $array [, bool $preserve_keys = false ] )

第 2 引数についての説明はこちら。

preserve_keys: If set to TRUE numeric keys are preserved. Non-numeric keys are not affected by this setting and will always be preserved.

第 2 引数の TRUE でキーが数字とみなせる場合にもキーが保持されるようになります。

array_reverse(['1998' => 'car'], TRUE)
// => [1998 => 'car']

ただし、キーが FALSE である要素の場合は第 2 引数の有無にかかわらずキーが消失します。 これが仕様なのかどうなのかはよくわかりませんが、思わぬところでハマる原因にはなりそうです。

FALSE の場合:

array_reverse([FALSE => 'car'])
// => ["car"]

ちなみに、キーが NULL や空文字列の場合は、 FALSE とはまた違った挙動となります。

    array_reverse([NULL => 'car'])
    // => ["" => "car"]

    array_reverse(['' => 'car'])
    // => ["" => "car"]

注意が必要ですね。 気をつけないと。