- カテゴリ: collection
- 掲載バージョン: Laravel 12・PHP 8.4
- 名前空間 / FQCN / コマンド:
Illuminate\Support\Collection::union - 関連: merge / concat / replace / intersectByKeys / unique
- 変更履歴: —
要点(TL;DR)
- 何に使うか:左(元)コレクションのキーを優先し、存在しないキーだけ右側から追加する。
- 最低限の使い方:
$a->union($b) - よくある罠:
- 値の“集合(ユニーク)結合”ではない(キーで結合)
- 数値キーは左が優先され、右の同一キーは無視される
- 連番配列同士だと何も増えないことがある(例:
[1,2]∪[2,3]→[1,2])
概要
union は PHP の配列演算子 + と同等で、左側の既存キーを保ちつつ、右側にしかないキーを追加します。上書きは一切行いません。設定の“デフォルトを固定して一部だけ後から足す”といった用途に向きます。値ベースでユニークに結合したい場合は別手段(concat()->unique() など)を使います。
構文 / シグネチャ
/**
* 左コレクションのキーを優先し、存在しないキーだけ $items から追加する
*
* @param iterable|\Illuminate\Contracts\Support\Arrayable|\JsonSerializable|array $items
* @return \Illuminate\Support\Collection // 新しいインスタンス(非破壊)
*/
public function union($items);
- 引数(表)
| 引数 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|
| $items | iterable | Arrayable | JsonSerializable | array | はい | — | 右側に結合する要素群。キーの衝突時は無視される(左優先)。 |
- 戻り値:
Collection(新しいコレクション。元は変更しない) - 例外/副作用:なし(ただし大きな入力ではメモリ消費に注意)
コレクション特性(collectionカテゴリの追加事項)
- チェーン可:可(非破壊)
- 破壊的/非破壊:非破壊
- キー保持:保持(左のキーが優先)
- LazyCollection 対応:非対応(等価処理には一度
collect()で実体化する必要あり。遅延性は失われる) - 計算量の目安:O(n + m)
- 入出力対応(小例):
collect(['a'=>1, 'b'=>2])->union(['b'=>9,'c'=>3])→['a'=>1,'b'=>2,'c'=>3]collect([1,2])->union([2,3])→[1,2](数値キー 0,1 が左優先のため増えない)
使用例
最小例
<?php
use Illuminate\Support\Collection;
$base = collect(['a' => 1, 'b' => 2]);
$extra = ['b' => 99, 'c' => 3];
$result = $base->union($extra);
// 結果: ['a' => 1, 'b' => 2, 'c' => 3]
// 'b' は左優先で 2 のまま、'c' だけ追加
実務例:固定デフォルトを崩さずにユーザー入力を“追記”
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
function buildOptions(Request $request): Collection
{
// システム固定値(上書き不可)
$locked = collect([
'timeout' => 30,
'retry' => 2,
'region' => 'jp-east',
]);
// ユーザーが足せる拡張項目(上記キーは無視される)
$userAppendables = $request->only(['tags', 'note', 'priority']);
// union なら固定値を守りつつ、未知キーだけ追記できる
return $locked->union($userAppendables);
}
よくある落とし穴・注意
- 値のユニーク結合ではない:キーで比較します。値ベースで重複排除したいなら
concat()->unique()、順序を保ちたいならvalues()も検討。 - 数値キーの罠:
[1,2] ∪ [2,3]は[1,2]のまま。右の0,1キーは既に存在するため無視されます。 - 深い配列は非再帰:ネスト配列のマージはしません。階層をマージしたいなら
Arr::dot()で平坦化してから統合する、またはmergeと個別ロジックを併用。 - LazyCollection 非対応:遅延で巨大データを扱う場合は
collect($lazy)により実体化が必要(メモリ増)。
代替・関連APIとの比較
- union:左優先で“存在しないキーだけ追加”。上書き禁止が要件なら最適。
- merge:連想キーは右が上書き、数値キーは末尾に追加・再採番。設定の上書きや追記に便利。
- concat:キー無視で末尾に連結。値ベースのユニーク化は
concat()->unique()。 - replace:連想キーを右で置換(数値キーはそのまま)。
- intersectByKeys:キー集合の共通部分だけを取得。
選定基準
- 既存値を守りたい → union
- 右で上書き・追記したい → merge
- 単純に後ろへ付けたい → concat
テスト例(Pest)
<?php
use Illuminate\Support\Collection;
it('keeps left values and adds only missing keys', function () {
$left = collect(['a' => 1, 'b' => 2, 0 => 10]);
$right = collect(['b' => 99, 'c' => 3, 1 => 30, 0 => 999]);
$u = $left->union($right);
expect($u->all())->toBe([
'a' => 1, // 左優先
'b' => 2, // 左優先
0 => 10, // 左優先(数値キーも同様)
'c' => 3, // 新規キーだけ追加
1 => 30, // 数値キー1は未使用だったため追加
]);
});
トラブルシュート(エラー別)
| 症状/エラー | 原因 | 対処 |
|---|---|---|
| 値ベースでユニーク結合できない | union はキー結合 | concat()->unique() へ置換。順序維持は values() 併用 |
| 右の値で上書きされない | union は左優先で上書きしない | merge を使用(連想キーは右が上書き) |
| 連番配列が増えない | 数値キー 0..n が左に存在し、右は無視された | 連番配列なら concat()->unique() を検討 |
| 大規模データでメモリが厳しい | union は新インスタンス生成で全要素保持 | 検索・フィルタを先に掛けて要素数を削減、Lazy が必要なら設計を見直す |
参考リンク
- Laravel公式:コレクション — union(Laravel 12)
https://laravel.com/docs/12.x/collections#method-union - Laravel公式:コレクション — merge / concat / replace / intersectByKeys
https://laravel.com/docs/12.x/collections - ソースコード:
Illuminate\Support\Collection::union
https://github.com/laravel/framework/blob/12.x/src/Illuminate/Support/Collection.php - PHPマニュアル:配列の結合(
+演算子)
https://www.php.net/manual/ja/language.operators.array.php

