Laravel collection are a powerful tool to work with arrays and data. They provide a fluent, convenient way to work with arrays that makes it easy to transform, filter, and manipulate data.
Laravel collections are an extension of the PHP array object, providing additional methods to work with arrays. In this article, we will look at how to create custom collections in Laravel.
When you make a call to the database with eloquent which has more than one result, it will return a collection of models. This collection is an instance of the Illuminate\Support\Collection
class. This class provides a lot of useful methods to work with the data.
However, sometimes you may to get data out of these collections in a custom way. For example, if you have a collection of blog posts and want to filter for the published ones you would create a filter like the following.
$publishedPosts = $posts->filter(function ($post) {
return $post->published;
});
But what if you want to use this filter in multiple places?
You could do something outlined in this article Improving PHP Callbacks where you create an invokable class to encapsulate the filter logic.
class PublishedFilter
{
public function __invoke($post)
{
return $post->published;
}
}
$publishedPosts = $posts->filter(new PublishedFilter());
This is a good way to encapsulate the filter logic, but it's not very readable. It would be better if you could call the filter method with a more readable name.
$publishedPosts = $posts->published();
This is where custom collections come in. You can create a custom collection class that extends the Laravel collection class and add your custom methods to it.
namespace App\Collections;
use Illuminate\Support\Collection;
class PostCollection extends Collection
{
public function published()
{
return $this->filter(function ($post) {
return $post->published;
});
}
}
Now you can use this custom collection in your models by overriding the newCollection
method.
namespace App\Models;
use App\Collections\PostCollection;
class Post extends Model
{
public function newCollection(array $models = [])
{
return new PostCollection($models);
}
}
Now you can call the published
method on your collection of posts.
$publishedPosts = $posts->published();
This is a simple example, but you can create custom collections with any methods you need. This can make your code more readable and maintainable by encapsulating the logic in a single place.