Maximize your Laravel blog's potential with SEO best practices and reach 10K monthly clicks on Google.
Preview the course for free
Benjamin Crozat New!
Benjamin Crozat The art of crafting web applications

Laravel Collections: methods to easily refactor your codebase

Benjamin Crozat — Updated on
Artboard

Hundreds of developers subscribed to my newsletter.
Join them and enjoy free content about the art of crafting websites!

Powered by

Laravel Collections are a powerful tool for manipulating arrays. They wrap native PHP array functions, create new handy ones and provide a fluent interface for working with them.

They’re also immutable, meaning they do not modify the original array. Instead, they return a new collection with the changes applied.

By using collections, you’ll stop wondering about:

And finally, your code will be more readable and easier to maintain.

Table of contents

Laravel Collections: methods to easily refactor your codebase

Laravel Collections methods I always use

Convert arrays into collections

First, let’s remind everyone that arrays can be transformed into collections using the collect() helper function. It’s that simple.

$collection = collect(); // Empty collection.
$collection = collect([1, 2, 3]); // Collection from an array.

If you take a look at collect()‘s source code, you’ll see you can also instantiate the \Illuminate\Support\Collection class.

use \Illuminate\Support\Collection;
$collection = new Collection([1, 2, 3]); // Object-oriented style.

each() instead of foreach loops

The most common use case for collections is to replace foreach loops.

use App\Models\Post;
$posts = Post::all();
foreach ($posts as $post) {
//
}

With collections, use the each() method:

use App\Models\Post;
Post::all()->each(function (Post $post) {
//
});

filter() for cleaning up

It is common practice to use temporary variables to store the result of a loop. Even if this is perfectly fine, collections allow you to do better.

$foo = [];
foreach ($bar as $baz) {
if ($baz->something()) {
$foo[] = $baz;
}
}
return $foo;

Instead, use the filter method and return the filtered collection.

return $bar->filter(function ($baz) {
return $baz->something();
});

How cool is that?

sum(), average(), min() and max() for handling numbers

Collections provide a set of methods to perform everyday mathematical operations on arrays.

Here’s how it looks using native PHP arrays:

$numbers = [1, 2, 3, 4, 5];
$sum = 0;
foreach ($numbers as $number) {
$sum += $number;
}
// $sum is now 15.
collect([1, 2, 3, 4, 5])->sum(); // 15

Of course, you can do more than add numbers.

$numbers = collect([1, 2, 3, 4, 5]);
$numbers->average(); // 3
$numbers->min(); // 1
$numbers->max(); // 5

Higher order messages, for even shorter code

Higher order messages are shortcuts that will make your code even more concise. Let me show you by example.

Can you refactor this code to a collection first?

foreach (User::where('foo', 'bar')->get() as $user) {
$user->notify(new SomeNotification);
}

Here’s the result:

User::where('foo', 'bar')
->get()
->each(function (User $user) {
$user->notify(new SomeNotification)
});

But we can do better.

Using higher-order messages, we can remove the anonymous function and directly access each User model notify() method.

That’s what I was saying; it feels like sorcery!

User::where('foo,' 'bar')
->get()
->each
->notify(new SomeNotification);

Say goodbye to unset() or lengthy code with only() and except()

Let’s say you only want to keep a few key-value pairs from an array.

This is how you’d do it in native PHP.

$original = [
'foo' => 'foo',
'bar' => 'bar',
'baz' => 'baz',
];
$keep = ['foo', 'bar'];
$new = array_intersect_key($original, array_flip($keep));

With Collections, it only takes one line of code thanks to the only() method.

$new = collect($original)->only('foo', 'bar');

Pretty damn cool, right?

Now, imagine we need to do the opposite. We want to exclude some key-value pairs from the array.

This is how you could do it using native PHP array functions.

$original = [
'foo' => 'foo',
'bar' => 'bar',
'baz' => 'baz',
];
unset($original['foo'], $original['bar']);

And now, here’s how to do it with Collections using the except() method:

$new = collect($original)->except('foo', 'bar');

dump() and dd() are built into collections

Instead of encapsulating your collection inside a dd() helper, you can call the dd() method that’s built-in collections.

// Before.
dd($collection->where('foo', 'bar'));
// After.
$collection->where('foo', 'bar')->dd();

If you don’t want to stop code execution, you want also use dump().

Play the lottery with random()

When writing factories, did you ever want to randomly pick a value from a given set? random() is the perfect method for this job.

class FooFactory extends Factory
{
public function definition()
{
return [
'foo' => collect(['Foo', 'Bar', 'Baz'])
->shuffle() // [tl! --]
->first(), // [tl! --]
->random(), // [tl! ++]
];
}
}

Get rid of the temporary variable with map()

This is something we all did:

  1. Get data as an array;
  2. Loop over it with foreach, transform each value and push them into a temporary array;
  3. Return the temporary array.

I don’t know for you, but the temporary variable always bothered me. I can illustrate it like so:

namespace App\Twitter;
use App\Twitter\Tweet;
use Illuminate\Support\Facades\Http;
class Client
{
public function tweets()
{
$tweets = Http::get('https://api.twitter.com/2/users/me')
->json('tweets');
$tmp = [];
foreach ($tweets as $tweet) {
$tmp[] = new Tweet(...$tweet);
}
return $tmp;
}
}

With Collections, we get rid of the temporary variable and make the code beautifully shorter.

namespace App\Twitter;
use App\Twitter\Tweet;
use Illuminate\Support\Facades\Http;
class Client
{
public function tweets()
{
return Http::get('https://api.twitter.com/2/users/me')
->collect('tweets')
->map(fn ($value) => new Tweet(…$value));
}
}

isEmpty() or isNotEmpty(), that’s the question

Instead of sticking to our old habit of using count() to check whether a Collection is empty or not, Laravel Collections provide a way more readable way of doing it.

if (! $collection->count()) { // [tl! --]
if ($collection->isEmpty()) { // [tl! ++]
// Do something if the collection is empty.
}
if ($collection->count()) { // [tl! --]
if ($collection->isNotEmpty()) { // [tl! ++]
// Do something if the collection is not empty.
}

It reads like English, and code like this makes everyone’s life easier.

Extend collections with your own methods

Among with other classes in Laravel, Collections are “macroable”. It means you can extend them with your own methods at runtime.

It all starts in the boot method of a Service Provider.

app/Providers/AppServiceProvider.php:

use Illuminate\Support\Str;
use Illuminate\Support\Collection;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
Collection::macro('pluralize', function () {
return $this->map(function ($value) {
return Str::plural($value);
});
});
}
}

Then, your custom methods will be available all over the codebase.

$collection = collect(['apple', 'banana', 'strawberry']);
// ['apples', 'bananas', 'strawberries');
$collection->pluralize();
Recommended

Learning a framework can be overwhelming, but time and execution will make you a master. Here are some best practices to help you toward your goal.

Learn why the "Using $this when not in object context" error happens, and let me show you the only way to fix.

Learn why the "Invalid argument supplied for foreach()" warning happens, and let me show you multiple ways to fix it.

There are multiple ways to check if an array is empty. Let me tell you about each of them and why and when you should use them.

Nailing a Laravel job interview can be a daunting task, but with the right preparation and mindset, you can set yourself up for success.

Debugging requires dissecting everything. Here's a list of all the one-line of code built-in ways to print arrays in PHP (and even Laravel-specific helpers).

Laravel 10 has been released on February 14, 2023. Let's dive into every relevant new feature and change.

Here's a case study for my blog in the programming niche, where I share everything I did to increase clicks by a huge amount since the beginning.

A soft delete in Laravel allows you to prevent mistakes by not removing sensitive data from your database right away.

I show you how to upgrade your Laravel 9 project to version 10 and help you decide whether the return on investment is worth it.

Powered by