Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Collections

An Eloquent query returns a collection rather than an array — an object with dozens of methods for processing data. The methods chain together, and the code reads like a description of what you want to get.

Creating

get() and all() return a collection. The collect() function makes one from a plain array:

$numbers = collect([1, 2, 3, 4, 5]);
 
$posts = Post::all();

Transforming and filtering

map() changes every item, filter() keeps the matching ones:

$titles = $posts->map(fn ($post) => strtoupper($post->title));
 
$popular = $posts->filter(fn ($post) => $post->views > 1000);
 
$even = collect([1, 2, 3, 4])->filter(fn ($n) => $n % 2 === 0)->values();

values() renumbers the keys after filtering.

The values of one field

$titles = $posts->pluck('title');
$titlesById = $posts->pluck('title', 'id');
 
$list = $posts->pluck('title')->implode(', ');

Searching

$first = $posts->first();
$firstPopular = $posts->first(fn ($post) => $post->views > 1000);
$post = $posts->firstWhere('slug', 'hello');
 
$hasDrafts = $posts->contains(fn ($post) => !$post->is_published);

Totals

$total = $orders->sum('total');
$average = $orders->avg('total');
$biggest = $orders->max('total');
$count = $orders->count();

These methods compute over data that is already loaded, without a new database query.

Sorting and grouping

$sorted = $posts->sortByDesc('views')->values();
 
$byCategory = $posts->groupBy('category_id');
 
$counts = $posts->countBy('category_id');
 
[$published, $drafts] = $posts->partition(fn ($post) => $post->is_published);

groupBy() returns a collection of collections keyed by the field's values. partition() splits a collection in two by a condition.

Parts of a collection

$top = $posts->take(3);
$rest = $posts->skip(3);
$rows = $posts->chunk(4);
$unique = collect([1, 2, 2, 3])->unique()->values();

chunk(4) splits into groups of four — handy for printing cards in rows.

A chain

$report = Order::with('user')->get()
    ->filter(fn ($order) => $order->status === 'paid')
    ->groupBy(fn ($order) => $order->user->name)
    ->map(fn ($orders) => $orders->sum('total'))
    ->sortDesc();

The result is the total of paid orders per customer, from largest to smallest.

A collection or a query

Collection methods work in PHP memory, while builder methods work in the database. Whatever can be done with a query, do with a query:

TaskIn the databaseIn memory
Pick the published onesPost::where(...)->get()Post::all()->where(...)
CountPost::count()Post::all()->count()

The right column loads the whole table only to throw most of it away.

Common mistake

Post::all()->count() and Post::count() give the same number, but the first loads every row of the table into memory. With ten records there is no difference; with a million the site crashes out of memory. Filter and count in the database, and use collections for what is already loaded.

Thanks for reading!

Donate to the site — we work hard for you.