Mastering Laravel Scope — A Comprehensive Guide with Code Examples

ArjunAmrutiya
4 min readJul 28, 2023

Introduction:
Laravel Scope is a powerful feature within Laravel’s Eloquent ORM that allows developers to define reusable query constraints. By leveraging Laravel Scopes, you can create cleaner, more efficient code and optimize database queries. In this comprehensive guide, we will explore various aspects of Laravel Scopes and demonstrate how to implement them effectively in your web applications.

1. Implementing Local Scopes in Laravel Eloquent

Local scopes allow you to encapsulate common query logic directly within your Laravel Eloquent models. By creating local scopes, you can easily apply specific constraints to your database queries, making your code more readable and maintainable.

Example:

Scope by Status: Implement a local scope to retrieve only active users from the database.

// User.php (Eloquent Model)

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

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

Scope by Category: Create a scope to fetch products belonging to a specific category.

// Product.php (Eloquent Model)

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

// Usage:
$categoryProducts = Product::byCategory(1)->get();

Scope with Parameters: Develop a scope to filter results based on user-defined criteria like date ranges.

// Post.php (Eloquent Model)

public function scopePublishedBetween($query, $startDate, $endDate)
{
return $query->whereBetween('published_at', [$startDate, $endDate]);
}

// Usage:
$postsBetweenDates = Post::publishedBetween('2023-01-01', '2023-07-31')->get();

2. Working with Global Scopes in Laravel

Global scopes are automatically applied to all queries on a specific Eloquent model. They are excellent tools for defining universal restrictions and ensuring consistency throughout your application.

Example:

Global Scope for Multi-Tenancy: Set up a global scope to retrieve data specific to a particular tenant in a multi-tenant application.

// TenantScope.php (Global Scope)

protected static function booted()
{
static::addGlobalScope('tenant', function (Builder $builder) {
$builder->where('tenant_id', auth()->user()->tenant_id);
});
}

// Usage:
$tenantPosts = Post::all(); // Automatically filtered for the authenticated user's tenant

Soft Deleting with Global Scope: Implement a global scope to automatically filter out soft-deleted records from all queries.

// SoftDeletingScope.php (Global Scope)

protected static function booted()
{
static::addGlobalScope('soft_delete', function (Builder $builder) {
$builder->whereNull('deleted_at');
});
}

// Usage:
$activePosts = Post::all(); // Excludes soft-deleted posts

3. Dynamic Scopes in Laravel

Dynamic scopes offer the ability to create versatile query constraints that accept parameters during runtime. This flexibility enhances the adaptability and power of your database queries.

Example:

Filtering Products by Price: Create a dynamic scope that allows users to filter products based on price ranges.

// Product.php (Eloquent Model)

public function scopePriceRange($query, $minPrice, $maxPrice)
{
return $query->whereBetween('price', [$minPrice, $maxPrice]);
}

// Usage:
$affordableProducts = Product::priceRange(10, 50)->get();

Sorting Records Dynamically: Implement a dynamic scope that enables users to sort records based on different criteria.

// Post.php (Eloquent Model)

public function scopeSortBy($query, $column, $direction = 'asc')
{
return $query->orderBy($column, $direction);
}

// Usage:
$sortedPosts = Post::sortBy('created_at', 'desc')->get();

4. Utilizing Laravel Scope for Security

Laravel Scopes can play a pivotal role in enhancing the security of your application. By controlling data access and permissions, you can bolster your app’s protection against unauthorized access.

Example:

Securing User Profiles: Develop a scope that restricts access to user profiles, allowing only the profile owner or admin to view sensitive information.

// UserProfile.php (Eloquent Model)

public function scopeAccessibleByUser($query, $userId)
{
return $query->where(function ($query) use ($userId) {
$query->where('user_id', $userId)->orWhere('is_public', true);
});
}

// Usage:
$userProfile = UserProfile::accessibleByUser(auth()->user()->id)->get();

Permissions Management: Create a scope to manage user permissions and access rights to specific resources.

// Resource.php (Eloquent Model)

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

// Usage:
$accessibleResources = Resource::accessibleByRole('admin')->get();

5. Best Practices for Laravel Scope Usage

To make the most of Laravel Scopes, it’s essential to follow best practices that ensure maintainable and efficient code.

Example:

Scope Reusability: Illustrate the benefits of reusable scopes and how they contribute to a cleaner codebase.

// Post.php (Eloquent Model)

public function scopePublished($query)
{
return $query->where('published', true);
}

public function scopeFeatured($query)
{
return $query->where('featured', true);
}

// Usage:
$featuredPosts = Post::published()->featured()->get();

Avoiding Overly Complex Scopes: Demonstrate the importance of keeping scopes simple and focused to prevent potential issues.

// Order.php (Eloquent Model)

public function scopeShippedWithinDays($query, $days)
{
return $query->whereDate('shipped_at', '>=', now()->subDays($days));
}

// Usage:
$recentOrders = Order::shippedWithinDays(30)->get();

Testing Scopes: Show how to write unit tests for scopes to ensure their correctness and avoid regressions.

// Tests\Feature\PostTest.php

public function testScopePublished()
{
factory(Post::class)->create(['published' => true]);
factory(Post::class)->create(['published' => false]);

$publishedPosts = Post::published()->get();

$this->assertCount(1, $publishedPosts);
}

Conclusion

In conclusion, mastering Laravel Scopes is a game-changer for Laravel developers. By effectively implementing local, global, and dynamic scopes, you can streamline your database queries, boost security, and create a more organized codebase. Embrace the code examples and best practices provided in this guide to take your Laravel applications to the next level. Happy scoping!

--

--

ArjunAmrutiya

👋 Hey there! I'm Arjun Amrutiya, a passionate web developer and blogger who loves all things PHP, Laravel and Vue.js. Welcome to my Medium account!