【Laravel】Collectionの使い方完全ガイド|map・filter・reduce・groupByなど実務でよく使うメソッド一覧
はじめに
Laravelを使っていると、データベースから取得したレコードや配列データを加工する場面が頻繁にあります。
そのときに活躍するのが Collection(コレクション) です。PHPの配列をそのまま操作するより、はるかに読みやすく、メソッドチェーンで直感的に書けるのが特徴です。
この記事では、実務でよく使うCollectionのメソッドを厳選してコード例つきで解説します。
Collectionとは
CollectionはLaravelが提供する配列ラッパークラスです。Illuminate\\Support\\Collection として実装されており、PHPの配列を扱いやすくするための豊富なメソッドが用意されています。
collect() ヘルパ関数を使えば、簡単にCollectionを生成できます。
$collection = collect([1, 2, 3, 4, 5]);
Eloquentのクエリ結果は自動的にCollectionとして返されるため、モデルを使っている場合は意識せず恩恵を受けられます。
$users = User::all(); // Illuminate\\Database\\Eloquent\\Collection
よく使うメソッド一覧
map
各要素を変換して新しいCollectionを返します。元のCollectionは変更されません。
$prices = collect([100, 200, 300]);
$taxed = $prices->map(fn($price) => $price * 1.1);
// [110.0, 220.0, 330.0]
モデルのコレクションに対しても使えます。
$users = User::all()->map(fn($user) => [
'id' => $user->id,
'name' => $user->name,
]);
mapとtransformの違い
transform()は元のCollectionを直接変更します(破壊的操作)。map()は新しいCollectionを返す非破壊的操作です。実務ではmap()を使うほうが安全です。
filter / reject
条件に合う要素だけを残します。reject() は逆に条件に合う要素を除外します。
$numbers = collect([1, 2, 3, 4, 5, 6]);
$even = $numbers->filter(fn($n) => $n % 2 === 0);
// [2, 4, 6]
$odd = $numbers->reject(fn($n) => $n % 2 === 0);
// [1, 3, 5]
引数なしで呼ぶと null・false・空文字など偽値を除外します。
$clean = collect([1, null, 2, false, 3, ''])->filter();
// [1, 2, 3]
each
各要素に対して処理を実行します。戻り値は元のCollectionです。変換ではなく副作用(ログ出力・メール送信など)に使います。
$users->each(function ($user) {
Log::info("User: {$user->name}");
});
false を返すとループを中断できます。
$collection->each(function ($item) {
if ($item > 3) {
return false; // ループ中断
}
echo $item;
});
pluck
特定のキー(カラム)の値だけを取り出します。
$users = collect([
['name' => 'Alice', 'age' => 30],
['name' => 'Bob', 'age' => 25],
]);
$names = $users->pluck('name');
// ['Alice', 'Bob']
第2引数にキーを指定すると、連想配列として取得できます。
$users = User::all()->pluck('name', 'id');
// [1 => 'Alice', 2 => 'Bob', ...]
groupBy
指定したキーでグループ化します。
$orders = collect([
['status' => 'pending', 'amount' => 100],
['status' => 'completed', 'amount' => 200],
['status' => 'pending', 'amount' => 150],
['status' => 'completed', 'amount' => 300],
]);
$grouped = $orders->groupBy('status');
// [
// 'pending' => [['status' => 'pending', 'amount' => 100], ...],
// 'completed' => [['status' => 'completed', 'amount' => 200], ...],
// ]
クロージャを使えば動的なグループ化も可能です。
$grouped = $orders->groupBy(fn($order) => $order['amount'] >= 200 ? 'high' : 'low');
reduce
要素を畳み込んで単一の値を返します。合計・最大値・カスタム集計など柔軟に使えます。
$total = collect([100, 200, 300])->reduce(fn($carry, $item) => $carry + $item, 0);
// 600
第2引数は初期値です。省略すると最初の要素が初期値になります。
chunk
Collectionを指定サイズに分割します。大量データをバッチ処理するときに便利です。
$chunks = collect([1, 2, 3, 4, 5])->chunk(2);
// [[1, 2], [3, 4], [5]]
$chunks->each(function ($chunk) {
// バッチ処理
});
sortBy / sortByDesc
指定キーでソートします。
$users = collect([
['name' => 'Charlie', 'age' => 28],
['name' => 'Alice', 'age' => 30],
['name' => 'Bob', 'age' => 25],
]);
$sorted = $users->sortBy('age');
// Bob(25), Charlie(28), Alice(30)
$sorted = $users->sortByDesc('age');
// Alice(30), Charlie(28), Bob(25)
first / last
条件に合う最初・最後の要素を返します。
$users = collect([
['name' => 'Alice', 'age' => 30],
['name' => 'Bob', 'age' => 25],
['name' => 'Carol', 'age' => 35],
]);
$youngest = $users->sortBy('age')->first();
// ['name' => 'Bob', 'age' => 25]
$oldest = $users->sortBy('age')->last();
// ['name' => 'Carol', 'age' => 35]
引数にクロージャを渡すと条件付きで取得できます。
$adult = $users->first(fn($user) => $user['age'] >= 30);
// ['name' > 'Alice', 'age' > 30]
contains / doesntContain
指定した値や条件が含まれるか確認します。
$numbers = collect([1, 2, 3, 4, 5]);
$numbers->contains(3); // true
$numbers->doesntContain(10); // true
$users->contains('name', 'Alice'); // true
$users->contains(fn($u) => $u['age'] > 40); // false
unique
重複を除去します。
$tags = collect(['php', 'laravel', 'php', 'mysql', 'laravel']);
$unique = $tags->unique();
// ['php', 'laravel', 'mysql']
キーを指定すれば、そのキーの値で重複判定します。
$users->unique('email');
count / sum / avg / min / max
集計系メソッドです。
$prices = collect([100, 200, 300, 400]);
$prices->count(); // 4
$prices->sum(); // 1000
$prices->avg(); // 250.0
$prices->min(); // 100
$prices->max(); // 400
キーを指定することもできます。
$orders->sum('amount');
$orders->avg('amount');
実務でよく使うパターン
APIレスポンスの整形
$users = User::all()->map(fn($user) => [
'id' => $user->id,
'name' => $user->name,
'email' => $user->email,
])->values(); // インデックスをリセット
条件フィルタリング後の集計
$totalRevenue = Order::all()
->filter(fn($order) => $order->status === 'completed')
->sum('amount');
グループ化して件数を取得
$statusCounts = Order::all()
->groupBy('status')
->map(fn($group) => $group->count());
// ['pending' => 5, 'completed' => 12, 'cancelled' => 2]
pluckでIDリストを生成してIN句に使う
$categoryIds = Category::where('active', true)->pluck('id');
$products = Product::whereIn('category_id', $categoryIds)->get();
Lazyコレクションとの使い分け
通常のCollectionはすべての要素をメモリに展開してから処理します。数万件以上のデータを扱う場合は LazyCollection を使うことでメモリを節約できます。
// 通常のCollection:全件メモリに載る
$users = User::all()->filter(...);
// LazyCollection:1件ずつ処理
User::cursor()->filter(...)->each(function ($user) {
// 処理
});
| Collection | LazyCollection | |
|---|---|---|
| データ取得 | 全件一括 | 1件ずつ(カーソル) |
| メモリ使用 | 多い | 少ない |
| 向いている場面 | 少量データ・加工 | 大量データ・ストリーム処理 |
cursor() はEloquentのクエリに対して使え、PDOのカーソルで1件ずつフェッチします。
まとめ
LaravelのCollectionを使いこなすことで、PHPの配列操作より可読性が高く、バグの少ないコードが書けるようになります。
| メソッド | 用途 |
|---|---|
| map | 各要素を変換する |
| filter / reject | 条件で絞り込む |
| each | 副作用の処理を実行 |
| pluck | 特定カラムを取り出す |
| groupBy | グループ化 |
| reduce | 畳み込み集計 |
| chunk | 分割してバッチ処理 |
| sortBy / sortByDesc | ソート |
| first / last | 先頭・末尾を取得 |
| contains | 存在確認 |
| unique | 重複除去 |
| count / sum / avg | 集計 |
まずは map・filter・pluck・groupBy の4つを使いこなすことを目指してみてください。実務の大半のケースはこの4つで対応できます。



