Laravel Tutorial · Database and Eloquent · Lesson 17 of 27

Laravel Collections

Laravel's Collection class wraps arrays with dozens of chainable methods: map, filter, groupBy, sum, sortBy, pluck, keyBy, chunk and more. Eloquent results are collections too.

Create a free account to save this page, take notes and track your progress. Sign in

Working with collections

collect([...]) wraps an array; every Eloquent get() returns one. Methods return new collections, so you can chain them:

Method Does
map, filter, reject, each Transform, keep, drop, loop
pluck('name'), keyBy('id'), groupBy('status') Reshape
sum, avg, max, min, count Aggregate (with a key or callback)
sortBy, sortByDesc, unique, values Order and clean
first, firstWhere, contains, every Find and test
chunk(3), take(5), partition(fn) Split
implode(', '), toArray(), toJson() Output

Lazy collections (LazyCollection, cursor()) process huge datasets without loading everything into memory.

Grouping, aggregating and reshaping data
<?php
$orders = collect([
    ['id' => 1, 'customer' => 'Ana', 'status' => 'paid', 'total' => 45.00],
    ['id' => 2, 'customer' => 'Ben', 'status' => 'pending', 'total' => 12.50],
    ['id' => 3, 'customer' => 'Ana', 'status' => 'paid', 'total' => 99.00],
    ['id' => 4, 'customer' => 'Cleo', 'status' => 'refunded', 'total' => 30.00],
    ['id' => 5, 'customer' => 'Ben', 'status' => 'paid', 'total' => 25.00],
]);

$paid = $orders->where('status', 'paid');
echo 'paid revenue: ', $paid->sum('total'), ', average: ', round($paid->avg('total'), 2), "\n";
echo 'customers: ', $orders->pluck('customer')->unique()->sort()->implode(', '), "\n";

$byCustomer = $paid->groupBy('customer')->map(fn ($group) => $group->sum('total'))->sortDesc();
foreach ($byCustomer as $name => $total) {
    echo "  $name: $total\n";
}

[$big, $small] = $orders->partition(fn ($o) => $o['total'] >= 30);
echo 'big orders: ', $big->pluck('id')->implode(','), ' | small: ', $small->pluck('id')->implode(','), "\n";

echo 'order 3 by key: ', $orders->keyBy('id')->get(3)['customer'], "\n";
echo 'any refunds? ', $orders->contains('status', 'refunded') ? 'yes' : 'no', "\n";
echo 'pages of 2: ', $orders->chunk(2)->map(fn ($c) => $c->pluck('id')->implode('+'))->implode(' | '), "\n";
echo json_encode($orders->map(fn ($o) => strtoupper($o['customer'][0]).$o['id'])->values()), "\n";

Output

paid revenue: 169, average: 56.33
customers: Ana, Ben, Cleo
  Ana: 144
  Ben: 25
big orders: 1,3,4 | small: 2,5
order 3 by key: Ana
any refunds? yes
pages of 2: 1+2 | 3+4 | 5
["A1","B2","A3","C4","B5"]

Run this on your computer — see “Get Started” for setup.

Test yourself

Which collection method groups orders into a nested collection per status?

  1. pluck('status')
  2. groupBy('status')
  3. keyBy('status')
  4. chunk('status')
Show answer

Answer: groupBy('status')

Was this page helpful?