連想配列を扱っていて、同じキーが複数の配列に出てきたとき「どの値が残るのか」「数値キーはどうなるのか」「マージと和演算子の違いは?」といった疑問を感じたことがある方は多いはずです。この記事ではPHPでarray_mergeを使って連想配列を結合する際に、キーが重複した場合の上書きルールや数値キー・文字列キーの扱い、array_mergeと他の方法(+演算子やarray_replaceなど)との比較や応用例を、最新情報に基づいて丁寧に解説します。
目次
PHP array_merge 連想配列 使い方と基本ルール
array_merge関数は複数の配列を結合して1つの配列を返す関数です。連想配列(文字列キーを持つ配列)に対して使うとき、キーが重複していたら後の配列の値で上書きされます。逆に数値キー(整数キー)の場合は再インデックスされて、0から連番が振られます。こうした動作は最新のPHPバージョンでも変わっておらず、仕様の一部です。
また、array_mergeは引数として複数の配列を取れるため、3つ以上の配列を順番にマージでき、それぞれの配列が持つキーや値が影響します。
文字列キーの重複時の挙動
複数の連想配列をarray_mergeで結合するとき、同じ文字列キーが複数の配列に存在すれば、**最後に現れる配列の値で上書きされます**。例えば最初の配列で ‘key1’=100 が定義されていて、後の配列で同じ ‘key1’=200 が定義されていれば、結果の配列では ‘key1’=200 になります。これはキーの名前が文字列の場合にのみ発生します。
数値キー(整数キー)の扱いと再インデックス
数値キーを持つ配列をマージすると、array_mergeは元の数値キーをそのまま維持せず、新しい配列に対して 0 から始まる連番のキーを振り直します。たとえば配列 A にキー 1,5 があり、配列 B にキー 2,3 があっても、マージ後はすべての要素が 0,1,2,3… のように再番号化されます。
これは配列の順序付けを重視した list 型の操作として理解でき、文字列キーとは異なる扱いになります。
複数の配列を結合する際の順序の影響
array_mergeは引数に与えられる配列の順序が結果に直接影響します。最初の配列の要素が先に入り、次の配列の要素がその後に続きます。重複する文字列キーがあれば、後ろにある配列の方の値で値が決定されます。順序を変えるだけで最終的な値が異なるので、どの配列を前にどれを後に指定するかが重要です。
array_merge vs 他の配列結合・上書き手法の比較
array_merge は便利ですが、他にも配列を結合・上書きする方法があります。ここでは+演算子(配列の和演算子)と array_replace、array_merge_recursive などとの違いを比較して、場面に応じた適切な選択方法を解説します。
+演算子による配列の結合
配列に対する+演算子は「和」演算を行い、重複する **文字列キー** があれば、**先頭の配列の値を保持**し、後の配列の値は無視されます。数値キーも文字列キーとして扱われる場合があるため、キーが文字列か整数かに注意が必要です。
この方式は文字列キーの上書きを避けたい場合に有用ですが、意図しない結果になることもあるため使う前に動作を確かめることをおすすめします。
array_replace の使いどころ
array_replace を使うと、第一配列のキーが第二配列でも存在する場合に第二配列の値で上書きされます。重複しないキーについては第一配列のものが保持されます。
つまり、array_merge と似ていますが、数値キーの再インデックス化などの影響を抑えたい場合に有効です。配列の構造やキーの種類を考えて使い分けると良いでしょう。
array_merge_recursive の特徴と注意点
array_merge_recursive は重複するキーがある場合、値を配列としてネストして保持する手法です。つまり、一方の値が単独だったとしても、重複すれば二つ以上の値を配列にして残します。
この動きはデフォルトで深い階層の配列にも適用され、文字列キー・数値キーの双方に影響します。値のネストによって用途によっては扱いが複雑になるため、使う前に結果をイメージする必要があります。
実践例:PHP array_merge 連想配列での典型パターン
具体的なコード例を見ながら、よくあるパターンでの動作を確認しましょう。実運用で混乱しやすいケースを取り上げて、どのような出力が得られるかを詳しく示します。
重複文字列キーがある連想配列のマージ例
以下は二つの連想配列で同じ文字列キーがある場合の例です。
$a = ['apple'=>1, 'banana'=>2];
$b = ['banana'=>20, 'cherry'=>3];
$c = array_merge($a, $b);
このとき結果$c は、
['apple'=>1, 'banana'=>20, 'cherry'=>3]
となります。キー banana は後の配列$b の値 20 で上書きされます。
数値キーが混在する配列のマージ例
次は数値キーと文字列キーが混じる例です。
$a = [0 => 'first', 'key'=>'value1'];
$b = [1 => 'second', 'key'=>'value2'];
$c = array_merge($a, $b);
この結果は、数値キー0,1 は再インデックスされ、順序通りに並び、文字列キー key は後の配列$b の値で上書きされます。
具体的には、
['first','value1','second','value2']
とはならず、
[0 =>'first',1 =>'key'=>'value2',2 =>'second']
とはならず、もっと正確に言うと、文字列キーはそのまま保持、数値キーの要素は順序どおりに連番で入ります。
多次元配列内の連想配列のマージ上書き傾向
多次元配列の場合、array_merge は最上位の配列の要素を結合しますが、ネストされた配列同士のキー重複は上書きされるかどうかは階層に依ります。array_merge_recursive を使えばネスト内でも重複がネストした配列に統合されますが、単純な array_merge では深くネストした文字列キー同士も、同じ文字列キーがあれば後の配列の値で上書きされます。
したがって設定データやコンフィグなど階層が深い場合は注意が必要です。
パフォーマンスとメモリ消費の観点から見る array_merge の限界
array_mergeは使い勝手が良い反面、大きな配列を何度も結合するとメモリ使用量と処理時間が無視できなくなります。特に数百万件の配列をマージすると、新しい配列が都度生成されるため、コピーコストが高くなります。
スマートな設計として、必要な部分のみをマージする、あるいは + 演算子や foreach ループによるマージなどを併用することで負荷を抑えることができます。
大きな配列を繰り返し結合する場合の注意点
配列のサイズが大きくなればなるほど、array_merge が配列を完全にコピーするコストがかかります。毎回 array_merge を呼び出す設計ではメモリ使用量が膨らむことがあります。こういった場合には、ループで要素を一つずつ追加する方法や、必要なキーだけを抽出して処理する方法が有効です。
代替手法を使った最適化例
例えば、+ 演算子で重複を無視したい文字列キーだけマージする、数値キーはループで追加するなど柔軟な戦略が取れます。また、array_replace を使えば最初の配列の多くの要素を保持しつつ、上書きが必要な部分だけ置き換えられます。再インデックスを抑えたいときはこれらを組み合わせることが有効です。
実務での応用例とトラブルシューティング
実際の現場では、設定ファイル、外部データのマッピング、セッションデータや POST データと既存データの統合などで array_merge を使うケースが多くあります。ここではよくある応用例とそれに伴う落とし穴、回避方法を紹介します。
設定値デフォルトとユーザー設定の統合
アプリケーションでデフォルト設定とユーザーが指定した設定をカスタマイズ可能にする例では、まずデフォルト配列を用意し、その後にユーザー設定配列を array_merge で重ねます。
こうすると重複するキーはユーザー設定で上書きされ、ユーザー未指定のキーはデフォルトが保持される仕組みになります。この手法はシンプルで直感的です。
POSTデータやセッションデータのマージでの意図しないキー消失に注意
フォームからの POST データを既存のセッション連想配列とマージすると、無意識にフォームで送られていない文字列キーのデフォルト値が失われたり、数値キーが再番号化されてしまったりすることがあります。
このようなケースでは数値キーの要素を意図して保持したいのかどうか、また文字列キーの重複がどれほどの影響を持つかを事前に確認することが大切です。
キーの種類が混在するデータ処理での設計上の工夫
文字列キーと数値キーが混ざるデータ構造を扱うときは、どちらのタイプのキーが主要かを設計で明確にしましょう。数値キーはリスト用途、文字列キーはマッピング用途というように用途を分けると、array_merge が意図通りに動きやすくなります。
また、キー重複を検知するためのユニットテストなどを導入すると、意図しない上書きエラーを早期に発見できます。
まとめ
PHPで連想配列を array_merge で結合する際には、文字列キーが重複した場合は後の配列の値で上書きされ、数値キーを持つ要素は再インデックスされるという挙動が基本です。複数の配列をマージする順序も結果に影響するため、順序の設計が非常に重要です。
また、+演算子や array_replace、array_merge_recursive など他の方法との比較を踏まえ、用途に応じて最適な手法を選ぶことが望まれます。大きな配列やネストの深い構造を扱う場合は、パフォーマンスとメモリ消費にも注意を払って設計することが、バグや予期せぬ動作を避ける鍵となります。
連想配列の結合や上書きのルールを正しく理解すれば、PHPでの配列操作がより確実で効率的になります。
コメント