Laravelのコレクション(Collection)は、配列データを直感的に操作するための便利なメソッドを数多く備えたクラスです。その中でもmergeメソッドは、複数のコレクションや配列を1つにまとめたいときに欠かせないメソッドです。
この記事では、mergeメソッドの基本的な使い方から、単純配列と連想配列での挙動の違い、mergeRecursive・union・concatといった似たメソッドとの使い分け、そして実務での活用例までを整理して解説します。
この記事でわかること
mergeメソッドの基本構文と戻り値の考え方- 単純配列と連想配列でキーがどう扱われるかの違い
merge・union・concat・mergeRecursiveの使い分け- 実務でmergeが役立つ場面(デフォルト値の上書き、データの統合)
- つまずきやすい注意点とその回避方法
mergeメソッドとは
mergeメソッドは、あるコレクションに対して別のコレクションや配列を結合し、新しいコレクションを返すメソッドです。呼び出し元のコレクションそのものは変更されない(非破壊的)ため、元データを保持したまま結合結果だけを別変数で受け取れます。
基本構文
// $collection: 結合元のコレクション
// $items: 結合するコレクションまたは配列
$new = $collection->merge($items);まずは最もシンプルな例を見てみましょう。
$collection1 = collect([1, 2, 3]);
$collection2 = collect([4, 5, 6]);
$mergedCollection = $collection1->merge($collection2);
$mergedCollection->all(); // [1, 2, 3, 4, 5, 6]この例では、mergeメソッドを使って$collection1と$collection2を結合し、新しいコレクション$mergedCollectionを作成しています。$mergedCollection->all()を呼び出すことで、結合された結果を配列として確認できます。
単純配列と連想配列での挙動の違い
mergeメソッドで最もつまずきやすいのが、キーの扱いが配列の種類によって変わる点です。数値キー(単純配列)と文字列キー(連想配列)で結果が異なります。
- 数値キーの場合:キーは振り直され、重複する値もそのまま追記される(要素は保持される)
- 文字列キーの場合:同じキーが存在すると、あとから結合した側の値で上書きされる
$collection1 = collect([1, 2, 3]);
$collection2 = collect([2, 3, 4]);
$mergedCollection = $collection1->merge($collection2);
$mergedCollection->all();
// [1, 2, 3, 2, 3, 4]
$collection = collect(['id' => 1, 'price' => 100]);
$merged = $collection->merge(['price' => 200, 'discount' => false]);
$merged->all();
/*
[
'id' => 1,
'price' => 200,
'discount' => false,
]
*/単純な配列では重複する要素を保持したまま結合し、連想配列では同名キー(price)の値が後勝ちで上書きされています。この「連想配列は上書き、単純配列は追記」というルールを押さえておくと、意図しない結果を防げます。
数値キーの場合は、元のキーの値が何であっても0から連番で振り直される(再採番)点も押さえておきましょう。次のように飛び番のキーを持つコレクションでも、結合後は末尾へ追加されたうえでキーが0から振り直されます。
$collection1 = collect([10 => 'a', 20 => 'b']);
$collection2 = collect([30 => 'c']);
$collection1->merge($collection2);
/*
[
0 => 'a',
1 => 'b',
2 => 'c',
]
*/元の10・20・30というキーは保持されず、0, 1, 2へ振り直されています。特定の数値キーを維持したまま補完したい場合は、キーを尊重するunionを使います(後述の比較表を参照)。
merge・union・concat・mergeRecursiveの使い分け
Laravel Collectionには結合系のメソッドが複数あり、PHP標準のarray_mergeとも挙動が異なります。目的に応じて使い分けられるよう、代表的なメソッドを比較表にまとめました。
| メソッド | 戻り値/破壊性 | 同名キーの扱い | 特徴・用途 |
|---|---|---|---|
merge | 新コレクション(非破壊) | 後勝ちで上書き | あとから渡した値を優先したいとき(設定の上書きなど) |
union | 新コレクション(非破壊) | 元のコレクションを優先(先勝ち) | 既存の値やキーを残しつつ、足りないキーだけ補完したいとき |
concat | 新コレクション(非破壊) | キーを無視して末尾に追加 | キーを気にせず単純に要素をつなげたいとき |
mergeRecursive | 新コレクション(非破壊) | 同名キーは配列にまとめる | 多次元配列を階層ごとに再帰的に結合したいとき |
push | 元コレクションを変更(破壊的) | 末尾に1要素だけ追加 | コレクションや配列ではなく「単一の値」を1つ追加したいとき |
array_merge(PHP標準) | 新しい配列を返す | 数値キーは再採番・文字列キーは後勝ち | コレクションではなく素の配列同士を結合するとき |
pushだけは他と性質が異なり、コレクションそのものを書き換える破壊的メソッドで、渡すのはコレクションや配列ではなく単一の値です。「コレクション同士をつなげたい」のか「値を1つ足したい」のかでmerge/concatとpushを選び分けます。素の配列同士であればcollect()を挟まずPHPのarray_mergeで済む場面も多く、キーの扱いはmergeと同じ考え方(数値キーは再採番・文字列キーは後勝ち)です。
unionとの違い(先勝ち/後勝ち)
$base = collect(['name' => '山田', 'role' => 'user']);
$add = ['role' => 'admin', 'active' => true];
$base->merge($add)->all();
// ['name' => '山田', 'role' => 'admin', 'active' => true] // roleは後勝ち
$base->union($add)->all();
// ['name' => '山田', 'role' => 'user', 'active' => true] // roleは元の値を維持「渡した値で上書きしたい」ならmerge、「元の値を優先して足りない分だけ補いたい」ならunionと覚えておくと選びやすくなります。
mergeRecursiveで多次元配列を結合する
$collection = collect(['id' => 1, 'role' => ['editor']]);
$merged = $collection->mergeRecursive([
'id' => 2,
'role' => ['admin'],
]);
$merged->all();
/*
[
'id' => [1, 2],
'role' => ['editor', 'admin'],
]
*/mergeRecursiveは、同名キーの値を上書きせずに配列としてまとめます。設定値やタグのように「複数の値を合成したい」ケースで役立ちます。
実務でmergeが役立つ場面
デフォルト値をリクエスト値で上書きする
$defaults = collect([
'per_page' => 20,
'sort' => 'created_at',
'order' => 'desc',
]);
// リクエストで指定された値だけを上書き
$options = $defaults->merge($request->only(['per_page', 'sort', 'order']));デフォルト設定をベースに、ユーザーが指定した項目だけを上書きする——という処理はmergeの典型的な使いどころです。指定がない項目はデフォルト値がそのまま残ります。
複数ソースのデータを1つにまとめる
キャッシュから取得したデータとデータベースの結果を統合したり、APIレスポンスをまとめたりする際にもmergeが活躍します。元のコレクションを壊さないため、結合前後のデータを比較しながら処理を組み立てられます。
Eloquent Collectionを結合するときの注意点
ここまではcollect()で作った基本のIlluminate\Support\Collectionを前提にしてきましたが、Eloquentクエリの結果(Model::all()や->get())はIlluminate\Database\Eloquent\Collectionという別クラスです。このクラスのmergeは挙動が上書きされており、配列キーではなくモデルの主キー(通常はid)で重複を判定します。
$usersA = User::whereIn('id', [1, 2])->get(); // id=1, id=2
$usersB = User::whereIn('id', [2, 3])->get(); // id=2, id=3
$merged = $usersA->merge($usersB);
$merged->pluck('id')->all();
// [1, 2, 3] ← id=2 は重複せず、$usersB 側のモデルで上書きされる基本のコレクションならid=2のモデルが2件残りますが、Eloquent Collectionでは同じ主キーのモデルは1件にまとめられ、あとから結合した側のモデルで置き換わります。複数のクエリ結果を重複なく統合したいときに便利な反面、「両方のレコードを残したい」場合は意図しない結果になります。次の点に注意してください。
- まだ保存していないモデル(主キーが未採番の
new Userなど)は主キーで判定できないため、重複扱いされず両方残ることがあります。 - 属性値だけを単純に足し合わせたい場合は、
toBase()で基本コレクションに変換してからmergeすると、配列キー基準の挙動に戻せます。 - 重複を主キーで消したくない・順序を制御したいときは、
concatで連結してからunique('id')で明示的に絞り込むほうが意図が明確です。
期待と異なる結果になりやすい失敗例
mergeは挙動を誤解しやすいメソッドです。実際にハマりやすいパターンを、原因と対処法とあわせて整理します。
失敗例1:重複が消えると思っていた
$a = collect([1, 2, 3]);
$b = collect([3, 4]);
$a->merge($b)->all();
// 期待:[1, 2, 3, 4]
// 実際:[1, 2, 3, 3, 4] ← 数値キーでは重複は排除されない
// 重複を除きたいなら unique() を続ける
$a->merge($b)->unique()->values()->all(); // [1, 2, 3, 4]失敗例2:戻り値を受け取っていない
$options = collect(['per_page' => 20]);
$options->merge(['per_page' => 50]); // 戻り値を捨てている
$options->get('per_page'); // 20 のまま(mergeは非破壊)
// 正しくは戻り値を受け取る
$options = $options->merge(['per_page' => 50]);
$options->get('per_page'); // 50失敗例3:ネストした配列まで結合されると思っていた
$config = collect(['options' => ['a' => 1]]);
$merged = $config->merge(['options' => ['b' => 2]]);
$merged->get('options');
// 期待:['a' => 1, 'b' => 2]
// 実際:['b' => 2] ← options キーごと後勝ちで上書きされる
// 階層ごとに結合したいなら mergeRecursive
$config->mergeRecursive(['options' => ['b' => 2]])->get('options');
// ['a' => 1, 'b' => 2]いずれも「mergeは浅く・非破壊で結合し、数値キーの重複は残す」という原則を押さえていれば防げます。重複排除はunique、階層結合はmergeRecursive、キー維持はunion——と目的別に組み合わせて使いましょう。
mergeを使うときの注意点
- 連想配列は上書きされる:同名キーがある場合、あとから渡した値で置き換わります。値を残したい場合は
unionを検討してください。 - 非破壊的である:
mergeは新しいコレクションを返すだけで、元の変数は変わりません。結果は必ず戻り値を受け取って使います。 - ネストした配列は浅く結合される:多次元配列を階層ごとに結合したい場合は
mergeではなくmergeRecursiveを使います。
関連するCollectionメソッド
コレクションを使いこなすうえで、結合以外のメソッドもあわせて押さえておくと処理の幅が広がります。用途に合わせて次の記事も参考にしてください。
- Laravel Collectionのmapメソッドを使ってデータ変換をスムーズに行おう:要素を変換して新しいコレクションを作る
- Laravel Collectionのfilterメソッドを使った要素のフィルタリング入門:条件に合う要素だけを抽出する
- Laravel Collectionのpluckメソッドを使って必要な情報を取り出す方法:特定のキーの値を一覧で取り出す
- Laravelコレクションのwhereメソッドでデータの条件抽出を簡単に実現:結合後のデータを条件で絞り込む
- Laravel Collectionのcount|要素数を数える方法とDBのcountとの違い:結合結果の件数を数える
- Laravel CollectionのgroupByで効率的なデータのグループ化:キーごとにデータをまとめる
- LaravelのCollectionで実際のプロジェクトに使用した物を紹介:実務での活用イメージをつかむ
まとめ
mergeメソッドは、配列やコレクションを非破壊的に結合できる便利なメソッドです。単純配列では要素を追記し、連想配列では同名キーを後勝ちで上書きするという挙動の違いを理解しておくことがポイントです。
「元の値を優先したいならunion」「キーを無視してつなげたいならconcat」「多次元配列を階層ごとにまとめたいならmergeRecursive」と、目的に応じて使い分けることで、Laravelのコレクション操作をより効果的に活用できます。

コメントを残す