merge — コレクションに配列/コレクションをマージ(同名キーは上書き)

collection
  • カテゴリ: collection
  • 掲載バージョン: Laravel 12・PHP 8.4
  • 名前空間 / FQCN / コマンド: Illuminate\Support\Collection::merge
  • 関連: union / concat / replace / mergeRecursive / put
  • 変更履歴: 特記事項なし

要点(TL;DR)

  • 用途:既存コレクションに別の配列/コレクションを“上書きマージ”する
  • 最低限の使い方:$merged = collect(['a' => 1])->merge(['a' => 9, 'b' => 2]);
  • よくある罠:
    • 文字キーは上書き数値キーは末尾に追加(再インデックス)
    • 深い階層は結合しない(再帰マージではない)→ mergeRecursive を検討
    • 原則非破壊(新インスタンスを返す)。元は変わらない

概要

merge は、配列や別のコレクションを取り込み、新しいコレクションを返します。文字キーが重複した場合は引数側で上書きされ、数値キーは末尾へ追加されます。設定の上書き、デフォルト値への追記など“後勝ち”でまとめたい場面に向きます。

構文 / シグネチャ

// Illuminate\Support\Collection
public function merge(array|\Illuminate\Support\Collection|\Illuminate\Contracts\Support\Arrayable|iterable $items): static;
  • 引数(表)
引数必須既定値説明
$itemsarray | Collection | Arrayable | iterableはいなしマージ対象。文字キーは上書き、数値キーは末尾追加
  • 戻り値Collection(元とは別の新インスタンス)
  • 例外/副作用:不正型を渡すと TypeError の可能性。ファイル/DB 等の副作用はなし

使用例

最小例

<?php

use Illuminate\Support\Collection;

$base   = collect(['a' => 1, 'b' => 2]);
$added  = ['b' => 20, 'c' => 3];

$merged = $base->merge($added);

// $merged: ['a' => 1, 'b' => 20, 'c' => 3]
// $base は変化しない

実務例:リクエスト値で設定を後勝ち上書き

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Collection;

function buildConfig(Request $request): array
{
    $defaults = collect([
        'paginate' => 20,
        'order'    => 'desc',
        'filters'  => ['status' => 'active'],
    ]);

    // リクエストから上書き(filters は再帰マージされない点に注意)
    $userInput = collect($request->only(['paginate', 'order', 'filters']));

    return $defaults->merge($userInput)->all();
}

数値キーの追加(再インデックス)

<?php

$merged = collect([10, 20])->merge([30, 40]);
// 結果: [10, 20, 30, 40] (0,1,2,3 と再インデックス)

コレクション固有の補足

  • チェーン可否:可(Collection を返す)
  • 破壊的/非破壊非破壊(新しいコレクションを返す)
  • キー保持:文字キーは上書き、数値キーは末尾追加(再インデックス)
  • LazyCollection:キー上書きを伴うため全件評価になりやすい。大量データは concat などの惰性的手段を検討
  • 計算量の目安:O(n + m)(n=元コレクション、m=マージ対象)
  • 入出力対応表
入力A入力B結果
['a'=>1,'b'=>2]['b'=>9,'c'=>3]['a'=>1,'b'=>9,'c'=>3](b を上書き)
[10,20][30,40][10,20,30,40](数値キーは追加)
['f'=>['x'=>1]]['f'=>['y'=>2]]['f'=>['y'=>2]]深い階層は上書き
collect(['k'=>1])collect(['k'=>2,'n'=>0])['k'=>2,'n'=>0]

よくある落とし穴・注意

  • 深い配列は結合されない['a'=>['x'=>1]]['a'=>['y'=>2]]merge すると a丸ごと上書き。→ 再帰的に結合したいなら mergeRecursive
  • 順序に意味がある場合union は「元を優先」し、既存キーを上書きしない。後勝ちが不要なら union
  • 大量データmerge は全件を新インスタンスへ集約するためメモリ増。ストリーム処理は concatLazyCollection の活用を検討
  • JSON/ArrayabletoArray() 相当で取り込まれる想定のため、意図せぬ型変換に注意

代替・関連APIとの比較

  • union($items):キーが重複しても元の値を保持(上書きしない)。設定の“初期値優先”に最適
  • concat($items):値を後ろに連結(キーは基本的に無視/再インデックス)。順序重視・大量データに
  • replace($items):キー一致の置換に特化(追加はしない)。既存キーのみ更新したいとき
  • mergeRecursive($items)深い階層も結合。ただし数値配列はネストが増えるなど期待と違う結果になり得る

テスト例(Pest)

<?php

use Illuminate\Support\Collection;

it('overwrites string keys and appends numeric keys', function () {
    $base   = collect(['a' => 1, 'b' => 2, 10, 20]);
    $merged = $base->merge(['b' => 99, 'c' => 3, 30, 40]);

    expect($merged->only(['a','b','c'])->all())
        ->toBe(['a' => 1, 'b' => 99, 'c' => 3]);

    expect($merged->values()->all())
        ->toBe([1, 99, 10, 20, 30, 40]); // 値の配列としては末尾に追加
});

トラブルシュート(エラー別)

症状/エラー原因対処
TypeError: merge(): Argument #1 must be ...渡した値が配列/反復可能でない[]collect() に包む/->all() で配列化して渡す
深い配列が結合されず消えたmerge は非再帰のため上位キーごと上書きmergeRecursive に切替/事前に array_replace_recursive 等で整形
期待と異なる順序になる数値キーは末尾追加・再インデックス順序重視は concat、またはキー付き配列にして制御
既存値を守りたいのに上書きされたmerge は後勝ちunion を使用

参考リンク

長野県・北アルプス地方在住のフリーランスWebプログラマー。
「落ち着くためのWeb開発」をテーマに、訪れる人が安心して使えるサービスづくりを心がけています。

LaravelやWordPressなどのWebアプリケーション開発を得意とし、技術面の安定性はもちろん、運用後も長く活用できる設計を大切にしています。
静かな山間の暮らしから生まれる視点で、シンプルかつ本質的な解決策をご提案します。

野鳥観察も趣味のひとつで、特にミソサザイ(Wren)に魅力を感じています。
小さな体に反して力強く上向きの尾羽、そして澄んだ鳴き声が遠くまで響く姿に、静かな存在感と芯の強さを感じます。
このサイト名「Laravel Wren」には、そんなミソサザイのように、小さくても確かな価値を届けたいという想いを込めています。

信頼できるパートナーとして、そして気軽に相談できる存在として、あなたのWebプロジェクトをサポートします。

Yudai Tsuyuzakiをフォローする