Streamlining Database Queries with Laravel Query Scopes

Streamlining Database Queries with Laravel Query Scopes

Laravel's query scopes provide an elegant way to encapsulate common query constraints, making your database queries more readable, reusable, and maintainable. Let's dive into how you can leverage query scopes in your Laravel applications.

Basic Query Scopes

To define a query scope, prefix a model method with scope:

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

You can then use this scope in your queries:

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

Scopes with Parameters

Scopes can also accept parameters:

class Post extends Model
{
    public function scopePopular($query, $minViews)
    {
        return $query->where('views', '>', $minViews);
    }
}

// Usage
$popularPosts = Post::popular(1000)->get();

Combining Multiple Scopes

One of the strengths of query scopes is their composability:

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

    public function scopeInStock($query)
    {
        return $query->where('stock', '>', 0);
    }

    public function scopeInCategory($query, $category)
    {
        return $query->where('category', $category);
    }
}

// Usage
$featuredElectronics = Product::active()
                              ->inStock()
                              ->inCategory('electronics')
                              ->orderBy('featured', 'desc')
                              ->get();

Global Scopes

Global scopes are automatically applied to all queries on the model:

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

// This will only return active users
$users = User::all();

You can also define global scopes as separate classes:

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

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

Removing Global Scopes

You can remove global scopes when needed:

User::withoutGlobalScope('active')->get();
// or
User::withoutGlobalScopes()->get();

Dynamic Scopes

You can create dynamic scopes for ultimate flexibility:

class User extends Model
{
    public function scopeOfType($query, $type)
    {
        return $query->where('type', $type);
    }
}

// Usage
$users = User::ofType('admin')->get();

Query scopes in Laravel offer a powerful way to encapsulate query logic, promoting cleaner, more maintainable code. By leveraging scopes, you can create expressive, reusable queries that make your application's database interactions more robust and easier to understand.

If this guide was helpful to you, subscribe to my daily newsletter and give me a follow on X/Twitter. It helps a lot!

Subscribe to Harris Raftopoulos

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe