When working with Eloquent collections, you might need to add specific functionality that applies only to certain model types. Laravel's new CollectedBy attribute provides a declarative way to customize collections without overriding model methods, making your code more maintainable and intention-clear.
Previously, customizing model collections required overriding the newCollection() method, but this new attribute-based approach offers a cleaner solution at the class level.
use Illuminate\Database\Eloquent\Attributes\CollectedBy; #[CollectedBy(CustomCollection::class)]class YourModel extends Model{ // Model implementation}
Let's explore a practical example with an e-commerce product catalog:
// Product Collection<?php namespace App\Collections; use Illuminate\Database\Eloquent\Collection; class ProductCollection extends Collection{ public function inStock() { return $this->filter(fn($product) => $product->stock_count > 0); } public function onSale() { return $this->filter(fn($product) => $product->discount_percentage > 0); } public function byPriceRange($min, $max) { return $this->filter(function($product) use ($min, $max) { $price = $product->getEffectivePrice(); return $price >= $min && $price <= $max; }); } public function topRated() { return $this->filter(fn($product) => $product->average_rating >= 4) ->sortByDesc('average_rating'); }} //Product modelnamespace App\Models; use App\Collections\ProductCollection;use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Attributes\CollectedBy; #[CollectedBy(ProductCollection::class)]class Product extends Model{ public function getEffectivePrice() { if ($this->discount_percentage > 0) { return $this->price * (1 - $this->discount_percentage / 100); } return $this->price; }}
The CollectedBy attribute simplifies collection customization while maintaining clean, readable code in your Laravel applications.
