Custom Query Builder Classes in Laravel | Mohamed Said       [Skip to content](#main)  [ ![](https://cdn.msaied.com/01KT78WE565VEMM3PSNQAAB0MH.png) Mohamed SaidLaravel Backend Engineer ](https://www.msaied.com/public) - [Home](https://www.msaied.com/public)
- [Projects](https://www.msaied.com/public/projects)
- [Articles](https://www.msaied.com/public/articles)
- [Certificates](https://www.msaied.com/public/certificates)
- [About](https://www.msaied.com/public#about)

           [  Contact](https://www.msaied.com/public#contact) Menu 

Menu
----

Close 

 - [HomeStart here](https://www.msaied.com/public)
- [ProjectsCase studies](https://www.msaied.com/public/projects)
- [ArticlesEngineering notes](https://www.msaied.com/public/articles)
- [CertificatesCredentials](https://www.msaied.com/public/certificates)
- [AboutHow I work](https://www.msaied.com/public#about)
- [ContactGet in touch](https://www.msaied.com/public#contact)

  [Start a conversation](https://www.msaied.com/public#contact) [WhatsApp](https://wa.me/201094619204) [Email](mailto:hello@msaied.com) 

 1. [Home](https://www.msaied.com/public)
2. /
3. [Articles](https://www.msaied.com/public/articles)
4. /
5. Laravel Macro-Free Extensibility: Custom Query Builder Classes and Fluent Scopes

 Laravel Macro-Free Extensibility: Custom Query Builder Classes and Fluent Scopes
=================================================================================

 Skip global macros and reach for typed, testable custom query builder classes in Laravel. Learn how to bind a dedicated builder per model, compose fluent scopes, and keep your query logic discoverable.

 ![](https://cdn.msaied.com/01M22N44A70A5MC2S599JP0MPH.webp) [Mohamed Said](https://www.msaied.com/public#person) Published 11 Sep 2026 · Updated 11 Sep 2026 · 1 min read

ShareCopy linkCopied

 ![Laravel Macro-Free Extensibility: Custom Query Builder Classes and Fluent Scopes](https://cdn.msaied.com/658/b45c3cc06b92a332e526bed9bb1f826d.png) 

  On this page +1. [The Problem With Macros and Scope Sprawl](#the-problem-with-macros-and-scope-sprawl)
2. [Binding a Custom Builder to a Model](#binding-a-custom-builder-to-a-model)
3. [IDE and Static Analysis Benefits](#ide-and-static-analysis-benefits)
4. [Composing Complex Conditions as Named Methods](#composing-complex-conditions-as-named-methods)
5. [Testing the Builder in Isolation](#testing-the-builder-in-isolation)
6. [Sharing Behaviour Across Builders](#sharing-behaviour-across-builders)
7. [Takeaways](#takeaways)

 The Problem With Macros and Scope Sprawl
----------------------------------------

Local scopes work fine for a handful of filters, but once a model accumulates a dozen `scope*` methods they become a flat, unsorted list with no grouping, no type hints on the builder return, and no IDE-friendly autocomplete. Macros are worse — they're global, invisible to static analysis, and silently overwrite each other.

The solution Laravel has always supported but rarely advertises: **a dedicated Eloquent query builder class per model**.

Binding a Custom Builder to a Model
-----------------------------------

Every Eloquent model exposes `newEloquentBuilder()`. Override it and return your own class that extends `Illuminate\Database\Eloquent\Builder`.

```php
