Customizing Collections in Laravel: Meet the CollectedBy Attribute

Customizing Collections in Laravel: Meet the CollectedBy Attribute

Ever wanted to customize your model collections without overriding methods? Laravel's new CollectedBy attribute makes this elegant and straightforward! Let's explore this clean approach to collection customization.

The CollectedBy Attribute

Instead of overriding the newCollection() method, you can now use a simple attribute:

use Illuminate\Database\Eloquent\Attributes\CollectedBy;

#[CollectedBy(PostCollection::class)]
class Post extends Model
{
    // Your model code here
}

Real-World Example

Here's how you might implement this in a blog system:

use Illuminate\Database\Eloquent\Attributes\CollectedBy;
use Illuminate\Database\Eloquent\Model;

// Custom Collection Class
class PostCollection extends Collection
{
    public function published()
    {
        return $this->filter->isPublished();
    }

    public function byCategory($category)
    {
        return $this->filter(fn($post) => $post->category_id === $category);
    }
}

// Model Using Custom Collection
#[CollectedBy(PostCollection::class)]
class Post extends Model
{
    protected $casts = [
        'published_at' => 'datetime',
    ];

    public function isPublished()
    {
        return !is_null($this->published_at) && 
               $this->published_at->isPast();
    }
}

// Usage
$posts = Post::all()->published();
$techPosts = Post::all()->byCategory(5);

This new attribute-based approach provides a cleaner, more declarative way to specify custom collections for your models. No more overriding methods - just declare and go!

If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!

Subscribe to Harris Raftopoulos

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe