HomeLARAVELHow do you use scopes in Laravel?

How do you use scopes in Laravel?

Laravel Eloquent provides a clean and elegant way to interact with your database. One of its powerful features is Eloquent Scopes, which help you organize and reuse query logic. In this blog, we will dive deep into scopes, their types, and how to use them effectively.


What is a Scope in Laravel?

A scope is a method in an Eloquent model that allows you to encapsulate commonly used query logic. Instead of repeating the same query in multiple places, you define a scope in the model and call it when needed.

Scopes make your code more readable, reusable, and maintainable.


Types of Scopes

Laravel provides two types of scopes:

  1. Local Scopes
  2. Global Scopes

1. Local Scopes

Local scopes are used to define query logic that can be reused in your model. They are optional and only applied when you call them.

Defining a Local Scope

To define a local scope, you create a method in your model and prefix it with scope. The convention is:

public function scope[ScopeName](Builder $query, $parameter = null)

Example: Filtering users by status.

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

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

    // Local scope with parameter
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }
}

Using Local Scopes

Once defined, you can use the scope like this:

use App\Models\User;

// Get all active users
$activeUsers = User::active()->get();

// Get all admin users
$adminUsers = User::ofType('admin')->get();

// Combine scopes
$activeAdmins = User::active()->ofType('admin')->get();

Notice that when calling the scope, you omit the scope prefix. scopeActive becomes active().


2. Global Scopes

Global scopes are applied automatically to every query on the model. They are useful when you want a query to always have certain conditions.

Defining a Global Scope

You can define a global scope in two ways:

  1. Using a class that implements Scope interface.
  2. Using a closure directly in the model’s booted method.

Method 1: Using a Scope Class

namespace App\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)
    {
        $builder->where('status', 'active');
    }
}

Apply the scope in the model:

namespace App\Models;

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

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

Now, all queries on User will only include active users:

$users = User::all(); // Only active users

Method 2: Using a Closure

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

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

Removing a Global Scope

Sometimes, you want to ignore a global scope for a particular query:

use App\Models\User;

// Ignore global scope
$allUsers = User::withoutGlobalScope(ActiveScope::class)->get();

// Or if defined with closure
$allUsers = User::withoutGlobalScope('active')->get();

Why Use Scopes?

Using scopes has several advantages:

  • DRY Code: Avoid repeating query logic in multiple places.
  • Readability: Makes queries expressive and easier to understand.
  • Reusability: Easily use scopes across different parts of your application.
  • Maintainability: Changing a scope affects all queries using it.

Best Practices

  1. Use local scopes for optional filters like active(), recent(), or ofType().
  2. Use global scopes for mandatory filters like soft deleted or active status.
  3. Chain multiple scopes to build complex queries.
  4. Keep scope names expressive for better readability.

Example: Combining Local and Global Scopes

$recentActiveAdmins = User::active()       // Local scope
                          ->ofType('admin') // Local scope
                          ->orderBy('created_at', 'desc')
                          ->get();

Here, the query is clean, readable, and reusable.


Conclusion

Laravel scopes are a powerful feature that allow you to write clean and maintainable query logic. Use local scopes for reusable optional query filters and global scopes for conditions that must always be applied. They help you keep your models organized and make your Eloquent queries more expressive.

Share: 

No comments yet! You be the first to comment.

Leave a Reply

Your email address will not be published. Required fields are marked *