- カテゴリ: collection
- 掲載バージョン: Laravel 12・PHP 8.4
- 名前空間 / FQCN:
Illuminate\Support\Collection::combine - 関連: zip / mapWithKeys / keys / values / merge
- 変更履歴: ―
要点(TL;DR)
- キー候補(現在のコレクション)と値リストを1:1で対応付けて連想配列化する。
- 最小コード:
collect(['name','age'])->combine(['George', 29]); - 罠:要素数の不一致/キーの重複は後勝ち/LazyCollectionでも最終的に全件走査になる。
概要
combine は、現在のコレクションの値をキーとして用い、引数で与えた配列/コレクションの各値を対応付け、連想配列(コレクション)を返します。CSV のヘッダー配列と行データの配列をマッピングするなど、**“見出し → 値”**の対応を一行で作る用途に向きます。公式ドキュメントの説明と例が分かりやすいです。 (laravel.com)
構文 / シグネチャ
public function combine($values): static
- 引数(表)
| 引数 | 型 | 必須 | 既定値 | 説明 |
|---|---|---|---|---|
| $values | array | \Traversable | \Illuminate\Support\Enumerable | ✔ |
- 戻り値:
Collection(array<string, mixed>相当の連想配列) - 例外/副作用:バージョンによってはキーと値の要素数不一致で例外相当の挙動だった記述があり(Laravel 5 系の解説例)、現行では値が余れば切り捨て/不足すれば
nullが入る実装に依存します。異なる環境での差異に注意。 (Stillat)
使用例
最小例
<?php
use Illuminate\Support\Collection;
$combined = collect(['name', 'age'])->combine(['George', 29]);
// ['name' => 'George', 'age' => 29]
print_r($combined->all());
実務例(CSVヘッダーと行データのマッピング)
<?php
use Illuminate\Support\Collection;
$headers = collect(['id', 'email', 'name']); // 1行目(ヘッダー)
$row = ['42', 'user@example.com']; // 値が足りないケース
$mapped = $headers->combine($row);
// 値が足りないキー 'name' には null が入る想定
// ['id' => '42', 'email' => 'user@example.com', 'name' => null]
print_r($mapped->all());
// 欲しい項目だけ抜き出して保存
$user = [
'email' => $mapped['email'],
'name' => $mapped['name'] ?? '(no name)',
];
よくある落とし穴・注意
- 要素数の不一致:値が不足すると未対応のキーに
null、値が余ると余剰分は無視されます(環境差の可能性があるためテストで固定化を)。 - キーの重複:キー側(現在のコレクション)に重複があると最後に現れたキーが上書きします。
- LazyCollection:
combine自体は使えますが、対応付けのために実質 O(n) 全走査になります。巨大入力では事前に件数や欠損を整えるほうが安全。 - Eloquent コレクション:返り値は ベースコレクションの連想配列になる前提で扱うと混乱が少ないです。
代替・関連APIとの比較
- zip:
[['name','George'], ['age',29]]の配列の配列を作る。キー→値の連想配列化が目的ならcombine。 (Stillat) - mapWithKeys:キー/値をコールバックで動的生成したいときはこちら。
- merge:連結/上書きが目的。キーと値の位置対応付けは行わない。
- keys / values:事前にキー側・値側を取り出して整形する補助。
- (純PHP)array_combine:同等目的だが要素数不一致でエラー/警告の扱いに注意。フレームワーク外でも使える。 (php.net)
テスト例(Pest)
<?php
use Illuminate\Support\Collection;
it('maps headers to row values and fills null for missing', function () {
$headers = collect(['id', 'email', 'name']);
$row = ['42', 'user@example.com'];
$mapped = $headers->combine($row);
expect($mapped->all())->toBe([
'id' => '42',
'email' => 'user@example.com',
'name' => null,
]);
});
トラブルシュート(エラー別)
| 症状/エラー | 原因 | 対処 |
|---|---|---|
| 期待よりキーが少ない/重複している | キー側コレクションに重複がある | keys()->duplicates() などで検出し、重複除去してから combine |
| 未定義インデックスっぽい結果/値がずれる | 値側の並び順が想定と不一致 | array_values() 相当でインデックスを詰めるか、values() を使ってから渡す |
| 旧環境で不一致時に例外/警告が出る | 旧バージョン由来の挙動 | 事前に件数を揃える・array_pad 等で補完・テストで期待値固定。 (Stillat) |
参考リンク
- Laravel Docs — Collections: combine / concat(公式) (laravel.com)
- Laravel Docs — Eloquent Collections(公式) (laravel.com)
- Stillat — Combining the Keys of a Collection With the Values of Another(Laravel 5 の解説と挙動の注意) (Stillat)
- PHP Manual —
array_combine(純PHPの代替) (php.net)
コレクション特記事項
- チェーン可否:可(非破壊)
- 破壊的/非破壊:非破壊(新しいコレクションを返す)
- キー保持:現在のコレクションの値がキーになる
- LazyCollection:対応(ただし最終的に全件消費)
- 計算量の目安:O(n)
- 入出力対応(サンプル)
| 入力キー(this) | 入力値($values) | 出力 |
|---|---|---|
['name','age'] | ['George', 29] | ['name'=>'George','age'=>29] |
['id','email','name'] | ['42','a@b.c'] | ['id'=>'42','email'=>'a@b.c','name'=>null] |

