Tech Verse Logo
Enable dark mode
Clean, Reusable Query Logic the Right Way: Laravel Global Scopes & Local Scopes

Clean, Reusable Query Logic the Right Way: Laravel Global Scopes & Local Scopes

Tech Verse Daily

Tech Verse Daily

4 min read

As Laravel applications grow, database queries tend to become repetitive and inconsistent. Conditions like is_active = true, deleted_at IS NULL, or tenant_id = ? start appearing everywhere.

Laravel solves this elegantly with Eloquent Scopes.

In this article, we’ll break down Global Scopes and Local (Custom) Scopes, explain when to use each, and demonstrate production-ready implementations following Laravel’s latest best practices.

What Is an Eloquent Scope?

An Eloquent scope is a way to encapsulate common query constraints inside your model so they can be reused, composed, and maintained centrally.

Laravel provides two types:

  1. Global Scopes – Automatically applied to every query

  2. Local Scopes – Explicitly applied when needed

1. Global Scopes

What Is a Global Scope?

A global scope automatically adds constraints to every query executed against a model.

Typical use cases include:

  • Soft deletes

  • Multi-tenancy

  • Active / published records

  • Data visibility rules

Creating a Global Scope (Class-Based)

Step 1: Create the Scope Class

php artisan make:scope ActiveScope

Step 2: Implement the Scope

namespace App\Models\Scopes;

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

class ActiveScope implements Scope
{
    public function apply(Builder $builder, Model $model): void
    {
        $builder->where('is_active', true);
    }
}

Step 3: Register the Scope on the Model

use App\Models\Scopes\ActiveScope;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected static function booted(): void
    {
        static::addGlobalScope(new ActiveScope);
    }
}

How It Works

Now, every query automatically includes:

WHERE is_active = true
User::all();        // Only active users
User::find(1);     // Only if active
User::count();     // Only active

No repetition. No mistakes.

Temporarily Disabling a Global Scope

Laravel allows precise control when you need it.

Disable a Specific Scope

User::withoutGlobalScope(ActiveScope::class)->get();

Disable All Global Scopes

User::withoutGlobalScopes()->get();

This is critical for admin panels, background jobs, or audits.

Anonymous Global Scopes (Quick Use)

For simple rules, Laravel allows inline scopes.

protected static function booted(): void
{
    static::addGlobalScope('published', function (Builder $builder) {
        $builder->where('published_at', '<=', now());
    });
}

Use this only when the logic is small and model-specific.

2. Local (Custom) Scopes

What Is a Local Scope?

A local scope is applied only when you explicitly call it.

They’re ideal for:

  • Reusable filters

  • Query composition

  • Readable fluent APIs

Creating a Local Scope

Local scopes are simply model methods prefixed with scope.

Example: scopeActive()

use Illuminate\Database\Eloquent\Builder;

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

Using the Local Scope

User::active()->get();
User::active()->where('role', 'admin')->get();

Laravel removes the scope prefix automatically.

Local Scope with Parameters

Example: scopeRole($role)

public function scopeRole(Builder $query, string $role): Builder
{
    return $query->where('role', $role);
}

Usage

User::role('manager')->get();
User::active()->role('admin')->get();

This makes queries expressive and composable.

Combining Global & Local Scopes

User::active()
    ->role('editor')
    ->latest()
    ->paginate(20);

✔ Global scope ensures visibility rules
✔ Local scopes handle business filters

This is the ideal architecture for scalable apps.

Removing Global Scope Inside a Local Scope

Sometimes you want a local scope that bypasses a global rule.

public function scopeWithInactive(Builder $query): Builder
{
    return $query->withoutGlobalScope(ActiveScope::class);
}

Usage:

User::withInactive()->get();

Best Practices (From Real Projects)

✔ Use global scopes for mandatory constraints
✔ Use local scopes for optional filters
✔ Prefer class-based global scopes
✔ Keep scopes query-only (no side effects)
✔ Name scopes clearly and intentionally

When NOT to Use Scopes

❌ Complex business workflows
❌ Authorization decisions
❌ Cross-model orchestration

Scopes are for query constraints, not domain logic.

Final Thoughts

Eloquent scopes are one of Laravel’s most elegant features. When used properly, they:

  • Eliminate query duplication

  • Enforce consistency

  • Improve readability

  • Scale naturally with your application

If you see the same where() clause repeated more than twice, it’s time for a scope.

    Latest Posts

    View All

    Clean, Reusable Query Logic the Right Way: Laravel Global Scopes & Local Scopes

    Clean, Reusable Query Logic the Right Way: Laravel Global Scopes & Local Scopes

    Mastering Custom Blade Directives in Laravel

    Mastering Custom Blade Directives in Laravel

    Laravel 12.44: Adds HTTP Client afterResponse() Callbacks

    Laravel 12.44: Adds HTTP Client afterResponse() Callbacks

    Laravel Artifact: Manage Your Media Easily

    Laravel Artifact: Manage Your Media Easily

    Handling Large File Uploads in Laravel: A Guide to Chunking & Resuming

    Handling Large File Uploads in Laravel: A Guide to Chunking & Resuming

    Next-Gen Laravel Deployment: FrankenPHP + Octane on Ubuntu VPS

    Next-Gen Laravel Deployment: FrankenPHP + Octane on Ubuntu VPS

    Speed Up Your Laravel App: Mastering Concurrent API Requests with Http::pool and Batch

    Speed Up Your Laravel App: Mastering Concurrent API Requests with Http::pool and Batch

    Beyond the Basics: Building Production-Ready APIs with Laravel

    Beyond the Basics: Building Production-Ready APIs with Laravel

    PHP 8.6: Expected Release Window and RFCs to Watch

    PHP 8.6: Expected Release Window and RFCs to Watch

    Downloading Files from External URLs in Laravel

    Downloading Files from External URLs in Laravel