その map()
、ちゃんと使えてますか?
LaravelでControllerのレスポンスを整形していると、
いつの間にか map()
や filter()
、pluck()
など、Collectionメソッドを使うようになります。
でも、こんな違和感がよぎったことはありませんか?
map()
とeach()
、なんとなく使い分けてるけど……違いって何?filter()
のあとにvalues()
つけるけど、これ必要なの?- 結局、Collectionって配列と何がどう違うんだっけ?
Laravel Collectionは便利です。書くのも短くなるし、チェーンで読める。
でもその“便利さ”に任せて使っていると、ある日コードがよくわからない状態で動いていたり、
意図しない動作にハマったりすることがあります。
この記事では、Laravel Collectionを「雰囲気で書いてる」状態から、
「意図して使う」状態にレベルアップすることを目指します。
特に、タイトルにもある map()
と each()
。
この2つ、ぱっと見は似てるけど、考え方も目的も真逆です。
似ているからこそ、よく使うからこそ、きちんと使い分けられるようにする。
そのための、“わかってるつもり”を脱出する入門書として書きました。
本記事のゴール
- Laravel Collectionの「考え方のベース」を理解する
- よく使うメソッドの“使いどころ”を正しく見極められるようになる
- 実務で書くCollectionコードが、読みやすく・壊れにくくなる

「Collectionって、“何ができるか”じゃなくて、“どう使い分けるか”が肝なんだよね〜」
- 0.1. 本記事のゴール
- 1. 🧱 Collectionとは何か?
- 1.1. Collectionは“配列のラッパー”であり“データ処理のフローを表す道具”
- 1.2. LaravelでどうやってCollectionが生まれるか?
- 1.2.1. アクセス方法の違い:
- 1.3. Collectionは「状態を持たない流れ」を書くための道具
- 1.4. ↑の何が嬉しいの?
- 1.4.1. ✅ 1. データの“持ち回し”がしやすくなる
- 1.4.2. ✅ 2. 意図しない“上書き”や“影響の連鎖”が起きにくいたいなバグが起きにくい
- 2. mapとeachの違い、ちゃんと使い分けできてる?
- 2.1. map():値を「変換」するためのメソッド
- 2.1.1. ❌ よくあるミス:
- 2.2. each():値に「処理」を加えるためのメソッド(変換はしない)
- 2.2.1. ⚠️ 注意点:eachで変換はできない
- 2.2.2. 💀 どうしてもeachで配列をいじりたいなら:
- 2.2.3. 🧠 mapとeachの違い、こう覚えると便利
- 2.3. 🙋♀️ じゃあどう使い分けるの?
- 2.3.1. ✅ 特徴
- 2.4. 💡 まとめ:mapとeachは性格が真逆
- 3. 実務でよく使う「美しいCollection」例3つ
- 3.1. ✅ パターン①:カテゴリ別に商品をグループ → 整形してJSONへ
- 3.1.1. 👀 出力例:
- 3.1.2. 📌 ポイント:
- 3.2. ✅ パターン②:条件でフィルタ → ソート → 数値変換して合計
- 3.2.1. 📌 ポイント:
- 3.3. ✅ パターン③:ログ記録しながら値を集計(map + tap)
- 3.3.1. 📌 ポイント:
- 4. ✨ まとめ:Collectionは「意図の見える処理」を書く道具
🧱 Collectionとは何か?
LaravelのCollection
は、PHPの配列をラップしたイテラブルなオブジェクトです。
でも、それだけ聞くと「要するに便利な配列のことね」と思って終わりがちです。
でも本当は、CollectionにはLaravelの思想──
つまり、「処理の意図をコードに乗せる」「状態を変えずに変換する」という考え方が色濃く出ています。
Collectionは“配列のラッパー”であり“データ処理のフローを表す道具”
たとえば、ただの配列に対してこんな処理をしたいとき:
$users = [
['name' => 'Alice', 'age' => 25],
['name' => 'Bob', 'age' => 32],
['name' => 'Charlie', 'age' => 28],
];
// 30歳未満のユーザー名を取り出したい
配列でやるとこう:
$result = [];
foreach ($users as $user) {
if ($user['age'] < 30) {
$result[] = $user['name'];
}
}
Collectionでやるとこう:
$names = collect($users)
->filter(fn($user) => $user['age'] < 30)
->pluck('name')
->values();
「フィルタして → nameを取り出して → 配列化する」
この人間の思考の順序がコードになります。
LaravelでどうやってCollectionが生まれるか?
Eloquentでデータを取ったときも、Collectionが使われています:
$users = User::where('active', true)->get();
この場合、中身は User
モデルのインスタンスで、map()
, filter()
, pluck()
などのメソッドが使えます。
一方、自分で配列から Collection を作るには collect()
を使います:
collect(['a', 'b', 'c']);
// => Illuminate\Support\Collection
この collect()
は Laravel のグローバルヘルパ関数で、内部的には new Collection()
しています。
🧠 補足:クエリビルダーからの get()
は普通の Collection(中身は stdClass)
Eloquentモデルではなく、クエリビルダーを使うと戻り値の中身が変わります:
$rows = DB::table('users')->where('active', true)->get();
// => Illuminate\Support\Collection(中身は stdClass)
アクセス方法の違い:
$rows->first()->name; // OK(stdClass)
$rows->first()['name']; // エラー(配列じゃない)
ビルダー | 戻り値の型 | 中身 |
---|---|---|
Eloquent | Illuminate\Database\Eloquent\Collection | モデルのインスタンス (User , etc.) |
クエリビルダー | Illuminate\Support\Collection | stdClass |
Collectionは「状態を持たない流れ」を書くための道具
map()
や filter()
などのメソッドは、元のデータを直接変えずに、新しい Collection を返します。
$updated = $original->map(...); // 元の $original はそのまま
↑の何が嬉しいの?
✅ 1. データの“持ち回し”がしやすくなる
たとえば、同じデータを使って
- 一方では絞り込みだけしたい
- もう一方ではソート+整形したい
みたいな処理をするとき、元のデータが書き換わらないことで、何度でも再利用できるのが便利です。
$filtered = $original->filter(...);
$summary = $original->map(...)->groupBy(...);
$original
はどちらの処理にも使えるし、処理ごとに変数を分けて書くことができます。
✅ 2. 意図しない“上書き”や“影響の連鎖”が起きにくいたいなバグが起きにくい
配列で値を操作していると、どこで変えたか分かりづらくなることってありませんか?
たとえば、複数の関数や処理の中で同じ $users
配列を使い回してるうちに、
「あれ?この時点でもう年齢加算されてた…」みたいな状態になってバグに気づく、みたいなこと。
$users = getUsers(); // 最初の配列
$updated = $users;
foreach ($updated as &$user) {
$user['age'] += 1; // ここで加算
}
// 後の処理でも $users を使おうとしたら、年齢が変わってる
Collectionを使っていると、こういった「いつの間にか変わってる問題」を避けやすくなります。
なぜなら、map()
などのメソッドは常に新しいCollectionを返すだけだからです。
$updated = $users->map(function ($user) {
$user['age'] += 1;
return $user;
});
// 元の $users はそのまま
🔑 「あとでまた使いたいデータが、勝手に変わってる…」という事故を防げる。
変換結果を“新しく作る仕組みを利用することで、安全に運用できます。
mapとeachの違い、ちゃんと使い分けできてる?
LaravelでEloquentのデータを扱っていると、get()
した結果がCollectionになっていることに気づく人は多いはずです。
最初は first()
や count()
、pluck()
あたりから自然と使い始めることが多いと思います。
でも開発に慣れてくると、「リストを加工したい」「値を変換したい」といった場面が出てきて、
そこで登場するのが map()
や each()
です。
この2つ、「なんとなく雰囲気で使ってる」人も多いと思いますが、本質はまったく違うものです。
この章では、mapとeachの違いを明確に整理し、使い分けの基準やよくあるミスを見ていきます。
map()
:値を「変換」するためのメソッド
$users->map(function ($user) {
return [
'name' => strtoupper($user['name']),
'age' => $user['age'] + 1,
];
});
- 各要素を変換し、新しいCollectionを返す
- 元のデータは変わらない(非破壊的)
return
が必須。これがないと意味がない- 「このリストをこう変えたい」と明示できるのが強み
❌ よくあるミス:
$users->map(function ($user) {
$user['is_admin'] = true;
});
// => [null, null, ...] が返る
変換のつもりで return
を書かないと、全部 null
になる。
「なんかうまく動いてると思ったらnull地獄だった」というバグ、たぶん人類全員一度はやる。

ぼくもreturn書き忘れて、nullにしちゃったことあるよ〜。
each()
:値に「処理」を加えるためのメソッド(変換はしない)
$users->each(function ($user) {
Log::info("User ID: {$user['id']}");
});
- 各要素に対して処理だけ行う
- 戻り値は元のCollectionのまま
return
は書いても無視される- 副作用(ログ出力・DB書き込みなど)を起こすための道具
⚠️ 注意点:eachで変換はできない
$users->each(function ($user) {
$user['is_admin'] = true;
});
これ、やった気になるけど実際は何も変わってない。
配列は値渡しなので、$user
はローカルコピーにすぎません。
(オブジェクトなら変わるけど、それでも意図が読みづらいコードになる)
💀 どうしてもeachで配列をいじりたいなら:
$users->each(function (&$user) {
$user['is_admin'] = true;
});
↑参照渡し(&)を使えばいじれるけど、🧙♀️黒魔術🧙♀️ 途端にコードが気持ち悪くなる。
「意図はmap、実装はeach(&)」みたいなコードは最悪。読む人をバグらせる。

eachで変換しようとしてたら、気づいたら副作用おばけになってたこと、あるよね〜
🧠 mapとeachの違い、こう覚えると便利
比較項目 | map() | each() |
---|---|---|
目的 | 値の変換 | 値の処理(副作用) |
戻り値 | 新しいCollection | 元のCollection |
returnの扱い | 必要(これが結果になる) | 無視される |
主な用途 | 整形・加工・変換処理 | ログ出力、通知送信、DB保存など |
副作用 | できるけど避けたい | 主目的が副作用 |
スタイル | 関数型っぽい | 命令的処理 |
🙋♀️ じゃあどう使い分けるの?
- 新しいリストがほしいとき → map()
- 例:ユーザー名だけ取り出す、値を整形する、変換した配列を返したい
- 処理だけしたいとき → each()
- 例:ログ出す、通知送る、何かを保存する、でもリスト自体はいじらない
- 「変えたいのにeach使ってる」やつ → 悪いコード
- 例:副作用と変換がごちゃ混ぜ、誰にも読まれない未来のレガシーコード製造中
🧠 補足:アロー関数(fn)の書き方と挙動
Laravelの記事やドキュメントでよく見かけるこの書き方:
$users->map(fn($user) => $user->name);
これは、PHP 7.4以降で使えるようになったアロー関数(arrow function)です。
✅ 特徴
fn($x) => 式
の1行構文で書けるreturn
を書かなくていい(暗黙のreturn)- 外側のスコープを自動でキャプチャ(
use
がいらない) - 複数行の処理は書けない(あくまで1行専用)
// 普通のクロージャ
$users->map(function ($user) {
return $user->name;
});
// アロー関数で短く書く
$users->map(fn($user) => $user->name);
参考 → PHP公式マニュアル(Arrow Functions)
Arrow functions were introduced in PHP 7.4 as a more concise syntax for anonymous functions…

アロー関数って現場では使ってるけど、本当にそういうのか、中の人は今日知ったんだって〜。
fn って書くと、なんだか賢くなった気がするよね〜。中身は同じなのに〜。
💡 まとめ:mapとeachは性格が真逆
LaravelのCollectionは、mapとeachを使い分けることで
「意図が伝わるコード」になっていきます。
- mapで変換することで、状態を持たない設計ができる
- eachで処理を明確に分離することで、読んだ人が安心できるコードになる
「書いたコードに意味を乗せる」ために、この2つはぜひ明確に使い分けていきましょう。
実務でよく使う「美しいCollection」例3つ
LaravelのCollectionは、ループで書く処理を、短く・意図的に・再利用可能に書けるのが強みです。
ここでは、実務でありがちなデータ加工のパターンを3つ紹介します。
✅ パターン①:カテゴリ別に商品をグループ → 整形してJSONへ
$products = collect([
['name' => 'iPhone', 'category' => 'スマホ'],
['name' => 'Galaxy', 'category' => 'スマホ'],
['name' => 'MacBook', 'category' => 'PC'],
]);
$grouped = $products
->groupBy('category')
->map(function ($items, $category) {
return [
'category' => $category,
'products' => $items->pluck('name')->values(),
];
})
->values();
return response()->json($grouped)
👀 出力例:
[
{
"category": "スマホ",
"products": ["iPhone", "Galaxy"]
},
{
"category": "PC",
"products": ["MacBook"]
}
]
📌 ポイント:
groupBy
で分類map
で整形(副作用なし!)pluck → values
で美しく並べ直し
✅ パターン②:条件でフィルタ → ソート → 数値変換して合計
$total = $orders
->filter(fn($order) => $order->status === 'completed')
->sortBy('completed_at')
->map(fn($order) => $order->total_price)
->sum();
📌 ポイント:
- 条件でフィルタ →
filter()
- 並び順制御 →
sortBy()
- 欲しい値だけ抜き出し →
map()
- 最後に合計 →
sum()
読み下すだけで処理の流れが見える。目にやさしい数値処理。
✅ パターン③:ログ記録しながら値を集計(map + tap)
$totals = $users->map(function ($user) {
return tap([
'name' => $user->name,
'orders_total' => $user->orders->sum('total_price'),
], function ($summary) use ($user) {
Log::info("Processed user {$user->id}", $summary);
});
});
📌 ポイント:
map()
で変換tap()
で副作用(ログ出力)を副流的に添える- 「データ変換」と「処理」をきれいに分ける書き方

tapは容易に使うとれびゅあー?がまゆをひそめるらしいから、あんまり詳しく書かないことにしたんだって。ケチだね〜。
✨ まとめ:Collectionは「意図の見える処理」を書く道具
LaravelのCollectionは、ただ便利なだけじゃない。
「このデータをどう扱いたいのか?」をコードに直接刻み込める設計になってます。
- ループでバラバラに書くより、流れで見せる
- 変換はmap、副作用はeach
- わかりやすさと再利用性を両立できる
Collectionを使うと、「どう処理するか」ではなく「何をしたいか」を表現できます。
意図が伝わるコードは、実装も保守も、ちょっとだけやさしくなる。
LaravelのCollectionは、そういう「書き味」を持った道具です。

今日もいっぱい勉強したね〜。文字数7800文字。おなかいっぱーい。
コメントを残す