Jens Segers on May 29 2014

Laravel collections are awesome

The Collection class in Laravel is really awesome. In Laravel, database query results are returned as a collection object, that "wraps" the actual results. The class contains a lot of handy methods that will make your work so much easier.

When I'm working with external API's, I often wrap the results in a collection so that I can use those methods:

use Illuminate\Support\Collection;

// Get the results from the API.
$results = json_decode($github->request('users/jenssegers/repos'));

// Wrap them in a collection.
$collection = new Collection($results);

// Sort descending by stars.
$collection->sortByDesc('stargazers_count');

// Get top 5 repositories.
$top5 = $leaderboard->take(5);

These are a few methods that I use quite often:

Lists

This method will return every value of a given key. The following example returns every user's email address, indexed by their user id.

$collection->lists('email', 'id');

I use it to get values to pass to a whereIn query, to get data for a pie chart or to pass data to a dropdown menu.

Filter

This will run a filter function over each of the items. If the callback returns true, it will be present in the resulting collection.

$collection->filter(function($user)
{
    if ($user->isNearby($me)) return true;
});

Most of the time you will be able to limit the results straight from the query, but in some cases this will come in handy when the filter is pretty difficult, when you're working on a cached collection or when you want to filter API results.

ToJson

Another great thing about collections is that they can easily be converted to json.

echo $collection->toJson();

When you cast a collection to a string, it will actually call the toJson method:

echo $collection;

Count

Something that's quite obvious is the count method, which just returns you how many items there are in the collection. One important thing to note here is that if you are using relations, execute the count method on the builder object and not on the collection object:

User::posts()->count();

And not:

User::posts->count();

That last example will first get all the post object of that user and wrap it in a collection, then the count method will tell you how many items there are in that collection. The first example however, will perform a count database query that will return the result a lot faster.

Take

Works just like the query builder, takes the first or last number of items.

$first5 = $collection->take(5);
$last5 = $collection->take(-5);

Sum

The sum method will return the sum based on the key or a callback function:

$collection->sum('points');

SortBy and sortByDesc

You can use sortBy or sortByDesc to sort the collection based on a key or a callback function. The first parameter is your key of the callback function, the second one is the sorting method (http://www.php.net/manual/en/array.constants.php).

$collection->sortBy('name');

// Sort descending by rating.
$collection->sortByDesc(function($item)
{
    return $item->rating;
});

More

There are a few more methods that you can see over here: https://laravel.com/docs/5.2/collections#available-methods

I hope I was able to show you how awesome the Laravel collection class is for handling database and API results.


Comments

RayWachaga 1 year ago

Thanks Jens Segers, this will come in handy some day I bet.


Yan 2 years ago

Hi,

Say I have 2 data in a column & I'd like to have the sum() of them.

1,000.00 2,5000.00

How do I use this as apparently any numbers after the comma (,) will be ignored.

{{ App\Invoice::sum('total_amount') }}

Neeltje Chanterie 2 years ago

Nice! I like the way you make your "top 5"! Helped me alot :D


Divo 3 years ago

What a great post and excellent framework. Thanks


Chris Andrew 3 years ago

$user->posts() in the Count example, not User::posts().


Pete 3 years ago

I would like to pull a count out of a collection for items that were updated in the past week, past month and today... can't get the syntax right and have not been able to find any examples to follow.

$filtered = $collection->where('updated', '>=', Carbon::now()->startOfWeek()); $count = $filtered->count();

Any ideas on how to get it to work?


Alexandru Furculita 3 years ago

There are and were even more powerful alternatives to Laravel Collections, like: https://github.com/schmittjoh/php-collection


jenssegers 3 years ago

@ Reivax Book::all() already returns a Collection.


Reivax 3 years ago

It doesn't work for me :'(

Argument 1 passed to Illuminate\Support\Collection::__construct() must be of the type array, object given, called in /var/www/project-noosphere/app/controllers/BookController.php on line 26 and defined

With this code: public function search() { $books = Book::all(); $collection = new Collection($books); $collection->sortByDesc('prix'); return View::make('search') ->with('collection', $books); }

Any ideas?


SimonErich 4 years ago

@Emerson Carvalho: in the Laravel Docs there is a point about attaching custom collection methods. You could use those to extend the default method. Just look in http://laravel.com/docs/eloquent#collections at the very end of the collection part.


Paul S 4 years ago

Excellent post, and great examples - many thanks.


Emerson Carvalho 4 years ago

how do I extend the collection? I have some ideas but I need to add methods to the Collection! Thanks