ルール
ラップ 配列 フィルタリング 結果 を array_values()
関数 のような array_filter() 保持する 元の キーを
これと同様に は バグを バグ が コードが コードが 数値
数値 インデックス 開始 から 0。
対応言語: PHPはじめに
PHPの array_filter() 要素をフィルタリングする際に、数値インデックス付き配列の場合でも元の配列キーを保持します。フィルタリング後 [0 => 'a', 1 => 'b', 2 => 'c'] インデックス1を削除すると、得られるのは [0 => 'a', 2 => 'c'] 数値キーにギャップがある場合、0から始まる連続したインデックスを期待するコードは、アクセス時に破損します。 $array[1] または連続するインデックスに関する仮定で反復処理を行うこと。この動作は、フィルタリングによって再インデックス化された配列が返される他の言語の出身の開発者を驚かせます。
なぜ重要なのか
コードの保守性: 非連続な配列キーは、特定の条件下でのみ現れる微妙なバグを引き起こします。フィルタリングされていない配列では正常に動作するコードが、ある仮定に基づいてフィルタリング後に不可解に失敗することがあります。 count($array) - 1 有効な最大インデックスです。根本原因が不明瞭なため、これらの問題のデバッグは時間の無駄になります。3つの要素を持つ配列を見ても、インデックス1で2番目の要素にアクセスできないからです。
JSONエンコーディングの問題: ~の場合 json_encode() 非連続なキーを持つ配列の場合、PHPはそれを配列ではなくオブジェクトとして扱い、その結果、 {"0":"a","2":"c"} ~の代わりに ["a","c"]。JSON配列を期待するフロントエンドコードが代わりにオブジェクトを受け取り、イテレーションや配列メソッドが機能しなくなります。PHP配列とJavaScript配列のこの不一致は、フィルタリング操作後にのみ現れる統合バグを引き起こします。
イテレーションとページネーションのエラー: 結果をページ分割したり、配列をチャンクに分割したりするコードは、キーが連続していない場合に機能しなくなります。0からループする count($array) 未定義のインデックスにアクセスします。使用中 array_slice() ページネーションの場合、位置に基づいて動作するものの元のキーを返すため、予期せぬ結果が生じます。これらのバグは、複雑なデータ処理パイプラインで複合的に発生します。
コード例
❌ 非準拠:
function getActiveUsers(array $users): array {
$activeUsers = array_filter($users, function($user) {
return $user['status'] === 'active';
});
// Bug: assumes index 0 exists and keys are sequential
$firstActive = $activeUsers[0] ?? null;
// Bug: JSON encodes as object if keys aren't sequential
return json_encode($activeUsers);
}
$users = [
['id' => 1, 'status' => 'inactive'],
['id' => 2, 'status' => 'active'],
['id' => 3, 'status' => 'active']
];
// Returns {"1":{"id":2...},"2":{"id":3...}} (object, not array)
getActiveUsers($users);
誤っている理由: フィルタリングによってインデックス 0 が削除された後、配列にはキーがあります。 [1, 2] ~の代わりに [0, 1], となり $activeUsers[0] 未定義。JSONエンコーディングは、キーが連続的ではないため、配列ではなくオブジェクトを生成し、配列を期待するフロントエンドコードを破損させます。
✅ 準拠済み:
function getActiveUsers(array $users): string {
$activeUsers = array_filter($users, function($user) {
return $user['status'] === 'active';
});
// Reindex to sequential keys starting from 0
$activeUsers = array_values($activeUsers);
// Now index 0 always exists for non-empty arrays
$firstActive = $activeUsers[0] ?? null;
// JSON encodes as proper array: [{"id":2...},{"id":3...}]
return json_encode($activeUsers);
}
$users = [
['id' => 1, 'status' => 'inactive'],
['id' => 2, 'status' => 'active'],
['id' => 3, 'status' => 'active']
];
// Returns [{"id":2...},{"id":3...}] (array, as expected)
getActiveUsers($users);
これが重要である理由: array_values() フィルタリングされた配列を0から始まる連続した数値キーに再インデックスし、インデックスアクセスを予測可能にし、JSONエンコーディングがオブジェクトではなく配列を生成するようにします。この関数は、どの要素がフィルタリングされたかに関わらず、期待通りに動作します。
まとめ
常にラップしてください array_filter(), array_diff(), および同様の関数と array_values() 連続した数値インデックスが必要な場合。これにより、非連続キーによる微妙なバグを防ぎ、JSONエンコーディングがオブジェクトではなく配列を生成することを保証します。パフォーマンスコストは、デバッグ時間の節約と比較して無視できる程度です。

