Laravel 12.19: Elegant Query Builders with PHP Attributes

July 7, 2025

Laravel 12.19: Elegant Query Builders with PHP Attributes

In Laravel 12.19, you can now use the #[UseEloquentBuilder] PHP attribute to assign a custom query builder to a model—no need to override newEloquentBuilder() anymore. It's cleaner and more maintainable.

Why Use a Custom Query Builder?

  • Keep models lean—models focus on relationships, not query logic.
  • Centralize reusable logic like wherePublished() in one place.
  • Organize code better—all custom queries live together.

The Old Way

// app/Models/Article.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Builders\ArticleBuilder;

class Article extends Model {
  public function newEloquentBuilder($query) {
    return new ArticleBuilder($query);
  }
}

The New Way

// app/Models/Article.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use App\Builders\ArticleBuilder;
use Illuminate\Database\Eloquent\Attributes\UseEloquentBuilder;

#[UseEloquentBuilder(ArticleBuilder::class)]
class Article extends Model {
  // no more override!
}

Builder Example

// app/Builders/ArticleBuilder.php
namespace App\Builders;

use Illuminate\Database\Eloquent\Builder;

class ArticleBuilder extends Builder {
  public function whereActive(): static {
    return $this->where('is_active', true);
  }

  public function recent(int $days = 7): static {
    return $this->whereDate('created_at', '>=', now()->subDays($days));
  }

  public function byCategory(string $slug): static {
    return $this->whereHas('category', fn($q) => $q->where('slug', $slug));
  }
}

Usage

$articles = Article::query()
  ->whereActive()
  ->recent(14)
  ->byCategory('tech')
  ->orderByDesc('published_at')
  ->paginate(10);

Pro Tips

  1. ✅ Only use when query logic gets reused.
  2. ⚙️ Keep method names flexible, e.g. recent(int $days).
  3. 🧪 Add unit tests for each builder method.
  4. 📘 Consider combining with global scopes.

This feature was introduced in Laravel 12.19 along with other improvements like AsFluent, FailOnException job middleware, and new response assertion methods.