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!