When building Laravel applications, you often write repeated query conditions. For example, if your app has users, you may want to fetch only active users in many places. Writing ->where('status', 'active') again and again can get messy.

This is where Laravel Query Scopes come in.

A query scope in Laravel is a way to define common query logic inside your Eloquent model. Once defined, you can reuse it across your application.

There are two types of scopes in Laravel:

  1. Local Scopes – reusable query conditions you call manually.

  2. Global Scopes – applied automatically to all queries of a model.

By using Laravel query scopes, you keep your code clean, reusable, and DRY (Don’t Repeat Yourself).

Why Use Laravel Query Scopes?

Problem Without Scope Solution With Scope
You repeat the same where conditions in multiple queries. Define once in model, reuse everywhere.
Risk of mistakes if conditions change later. Change in one place only (the scope).
Messy controllers and repositories. Clean and readable query syntax.

 

 Real-world example:

  • If you need to fetch only published blog posts, instead of writing:

Post::where('status', 'published')->get();

everywhere, you can define a scopePublished() inside your Post model and call:

Post::published()->get();

Much cleaner, right?

Types of Scopes in Laravel

Type Description Example
Local Scope You define and call it manually. User::active()->get()
Global Scope Automatically applied to all queries of a model. SoftDeletes trait (hides deleted rows automatically).

1. Local Scopes in Laravel

A local scope is a method inside your model that starts with the prefix scope.

Example: Active Users

In User.php model:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    // Local scope for active users
    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }
}

Now instead of writing:

$users = User::where('status', 'active')->get();

You can simply call:

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

Benefit: Cleaner, reusable, easier to maintain.


Local Scope with Parameters

You can also pass parameters.

Example: Filter posts by category.

class Post extends Model
{
    public function scopeCategory($query, $categoryId)
    {
        return $query->where('category_id', $categoryId);
    }
}

Usage:

$techPosts = Post::category(3)->get();

Real-world use: Filtering blog posts based on selected category.


2. Global Scopes in Laravel

A global scope is applied to all queries of a model automatically.

Example: Only Published Posts

namespace App\Models;

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

class Post extends Model
{
    protected static function booted()
    {
        static::addGlobalScope('published', function (Builder $builder) {
            $builder->where('status', 'published');
        });
    }
}

Now whenever you call:

 
Post::all();

It will only return posts with status = 'published'.

Real-world example:

  • Hide inactive products in an e-commerce store.

  • Hide banned users from a social app.


Removing Global Scope

Sometimes you may want to ignore a global scope.

Post::withoutGlobalScope('published')->get();

Real-world example: Admins may need to see all posts (published + drafts).


Built-in Global Scope Example – SoftDeletes

Laravel already uses global scopes in features like SoftDeletes.

When you use the SoftDeletes trait in your model:

use Illuminate\Database\Eloquent\SoftDeletes;

class Post extends Model
{
    use SoftDeletes;
}

All queries on Post will automatically exclude deleted rows.

👉 Example:

Post::all(); // excludes deleted posts
Post::withTrashed()->get(); // includes deleted posts

 


Combining Local and Global Scopes

You can use both together.

Example:

  • Global scope: Show only status = active.

  • Local scope: Further filter by role.

class User extends Model
{
    protected static function booted()
    {
        static::addGlobalScope('active', function (Builder $builder) {
            $builder->where('status', 'active');
        });
    }

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

Usage:

$admins = User::role('admin')->get();

This fetches only active admins.


Real-World Use Cases of Query Scopes

Use Case Type of Scope Example
Only active users Global User::all() (automatically filters)
Only published posts Global Post::all()
Filter posts by category Local Post::category(2)->get()
Products in stock Local Product::inStock()->get()
Orders by status Local Order::status('pending')->get()

Performance & Best Practices

  • ✅ Use local scopes for reusable filters.

  • ✅ Use global scopes for rules that should always apply (e.g., hide inactive users).

  • ✅ Keep scopes short and clear.

  • ✅ Avoid overusing global scopes because they may confuse new developers.

  • ✅ Always give parameters to local scopes if needed.


Example: Blog Application

Scenario:

You’re building a blog with posts. You want:

  • Show only published posts by default (global scope).

  • Ability to filter posts by author or category (local scopes).

Solution:

Post Model

 
class Post extends Model
{
    // Global scope
    protected static function booted()
    {
        static::addGlobalScope('published', function (Builder $builder) {
            $builder->where('status', 'published');
        });
    }

    // Local scopes
    public function scopeAuthor($query, $authorId)
    {
        return $query->where('author_id', $authorId);
    }

    public function scopeCategory($query, $categoryId)
    {
        return $query->where('category_id', $categoryId);
    }
}

Usage in Controller

 
$posts = Post::author(1)->category(3)->get();

 This will fetch published posts by author 1 in category 3.


Table: Laravel Query Scope Keywords vs Examples

Keyword Example
laravel query scope User::active()->get();
laravel global scope Post::all(); (only published posts)
laravel local scope Product::inStock()->get();
laravel eloquent scope Defined in model for reusability
laravel model scope scopeActive() method
laravel query scope example Blog filtering posts
global scope in laravel SoftDeletes
local scope in laravel example Filtering by category

Conclusion

  • Laravel query scope is a powerful feature to keep queries clean and reusable.

  • Use local scopes for conditions you call manually.

  • Use global scopes for conditions that must always apply.

  • Real-world apps like blogs, e-commerce, and CRMs heavily rely on scopes to simplify database queries.

  In short:

  • If you’re repeating queries → use local scope.

  • If you always need a condition → use global scope.