Menü schliessen
Created: December 5th 2025
Last updated: December 12th 2025
Categories: Laravel
Author: Nikola Jevtic

Custom Eloquent Scopes in Laravel: Build Reusable and Readable Query Logic Like a Pro

Introduction

As Laravel applications grow, query logic often becomes scattered across controllers, services, and repositories. This leads to duplication, inconsistent filtering behavior, and bloated code that becomes difficult to maintain. Laravel’s Eloquent ORM provides a clean and powerful solution: custom query scopes.

Eloquent scopes allow you to package reusable query constraints directly inside your models, ensuring that filtering, ordering, and constraints remain expressive and easy to understand. In this article, we explore the power of local and global scopes, walk through common use cases, examine real code examples, discuss dependencies and setup, and compare scopes to other approaches for organizing query logic.


Why Eloquent Scopes Matter

When you find yourself repeating the same query fragments in multiple places, such as filtering “active” users or ordering posts by publication date, the need for scopes becomes clear. Without scopes, you end up with:

  • Duplicated filtering logic across multiple controllers
  • Hard-to-read queries with repeated constraints
  • Inconsistent behavior when rules evolve over time
  • Tightly coupled code that’s difficult to test

Custom scopes eliminate these problems by centralizing query-related rules inside the model, where query intent is easiest to discover and reuse.


Use Cases: When Custom Scopes Shine

Scopes are ideal whenever you perform the same filtering or ordering repeatedly. Practical examples include:

  1. Filtering active, verified, or published records
  2. Querying soft-deleted models with custom rules
  3. Applying date-based constraints (recent posts, last login, etc.)
  4. Applying consistent ordering (e.g., newest first, highest rated)
  5. Combining multiple conditions such as active + subscribed users
  6. Building domain-specific query filters like “high-value customers”

Custom scopes help your application stay lean and expressive without bloating controllers or services.


Dependencies and Setup

Eloquent scopes come with Laravel out of the box—no additional installation is required.

There are two types of scopes:

  • Local Scopes — defined as methods inside the model and applied explicitly
  • Global Scopes — automatically applied to all queries for a model

Both follow predictable patterns and integrate seamlessly with the query builder.


Local Scopes: Clean, Reusable Query Logic

A local scope is a method in your model prefixed with scope.

Example: Filtering Active Users

Model:

class User extends Model
{
    public function scopeActive($query)
    {
        return $query->where('active', true);
    }
}

Controller:

$activeUsers = User::active()->get();

Readable, expressive, and easy to reuse.

Scope with Parameters

public function scopeRegisteredAfter($query, $date)
{
    return $query->where('created_at', '>', $date);
}

Use it like:

$recentUsers = User::registeredAfter(now()->subMonth())->get();

Chaining Multiple Scopes

Scopes chain cleanly:

$users = User::active()->registeredAfter('2025-01-01')->orderBy('name')->get();

Global Scopes: Automatic and Model-Wide

Global scopes apply automatically to all queries on a model and should be used with care.

Example: Ordering Posts by Published Date

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class PublishedOrderScope implements Scope
{
    public function apply(Builder $builder, Model $model)
    {
        $builder->orderBy('published_at', 'desc');
    }
}

Register the scope inside the model:

protected static function booted()
{
    static::addGlobalScope(new PublishedOrderScope);
}

Now every query automatically orders posts by published date unless explicitly removed:

Post::withoutGlobalScope(PublishedOrderScope::class)->get();

Because global scopes run implicitly, they can affect debugging and reporting queries if forgotten.


Advanced Techniques with Scopes

1. Conditional Scopes

You can apply scopes conditionally:

$users = User::when($isActive, fn($query) => $query->active())->get();

2. Combining Scopes with Aggregates

$customers = Customer::highValue()->withSum('orders as total_spent', 'amount')->get();

3. Scopes for Soft-Delete Logic

public function scopeWithTrashedOnly($query)
{
    return $query->onlyTrashed();
}

4. Scopes for Multi-Tenant Applications

Apply tenant constraints:

public function scopeForTenant($query, $tenantId)
{
    return $query->where('tenant_id', $tenantId);
}

Error Handling with Scopes

Scopes rarely cause errors, but common issues include:

  • Missing columns when refactoring database schema
  • Infinite loops when scopes call methods that re-trigger them
  • Scope conflicts with global scopes requiring explicit removal

To diagnose issues, use:

Model::withoutGlobalScopes()->toSql();

This helps inspect the generated SQL structure, though bindings are not included.


Performance Considerations

Scopes add no meaningful overhead because they only modify the query builder before SQL execution.

Best practices:

  • Keep scopes lightweight and avoid heavy computations
  • Be cautious with global scopes on large datasets
  • Prefer local scopes when possible to reduce side effects
  • Avoid N+1 problems by combining scopes with eager loading

Comparison with Alternative Approaches

Feature Eloquent Scopes Repositories / Services Inline Queries
Readability Excellent Good Poor
Reusability High High Low
Boilerplate Very Low Medium High
Complexity Low Medium Low

Conclusion

Custom Eloquent scopes are one of the most elegant tools in Laravel for organizing query logic. By encapsulating filtering and ordering rules inside your models, scopes promote clarity, reusability, and maintainability throughout your application. Whether you're cleaning up repetitive queries, enforcing consistent constraints, or building complex filtering pipelines, scopes provide a simple and expressive way to write high-quality Laravel code.

If your queries are getting unwieldy or repetitive, it’s time to refactor them using Eloquent scopes—your future self will thank you.