Could we help you? Please click the banners. We are young and desperately need the money
As Laravel applications grow, query logic often becomes scattered across controllers, services, and repositories. This leads to duplication, inconsistent filtering behavior, and bloated code that becomes difficult to maintain. Laravel’s Eloquent ORM provides a clean and powerful solution: custom query scopes.
Eloquent scopes allow you to package reusable query constraints directly inside your models, ensuring that filtering, ordering, and constraints remain expressive and easy to understand. In this article, we explore the power of local and global scopes, walk through common use cases, examine real code examples, discuss dependencies and setup, and compare scopes to other approaches for organizing query logic.
When you find yourself repeating the same query fragments in multiple places, such as filtering “active” users or ordering posts by publication date, the need for scopes becomes clear. Without scopes, you end up with:
Custom scopes eliminate these problems by centralizing query-related rules inside the model, where query intent is easiest to discover and reuse.
Scopes are ideal whenever you perform the same filtering or ordering repeatedly. Practical examples include:
Custom scopes help your application stay lean and expressive without bloating controllers or services.
Eloquent scopes come with Laravel out of the box—no additional installation is required.
There are two types of scopes:
Both follow predictable patterns and integrate seamlessly with the query builder.
A local scope is a method in your model prefixed with scope.
Model:
class User extends Model
{
public function scopeActive($query)
{
return $query->where('active', true);
}
}
Controller:
$activeUsers = User::active()->get();
Readable, expressive, and easy to reuse.
public function scopeRegisteredAfter($query, $date)
{
return $query->where('created_at', '>', $date);
}
Use it like:
$recentUsers = User::registeredAfter(now()->subMonth())->get();
Scopes chain cleanly:
$users = User::active()->registeredAfter('2025-01-01')->orderBy('name')->get();
Global scopes apply automatically to all queries on a model and should be used with care.
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class PublishedOrderScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder->orderBy('published_at', 'desc');
}
}
Register the scope inside the model:
protected static function booted()
{
static::addGlobalScope(new PublishedOrderScope);
}
Now every query automatically orders posts by published date unless explicitly removed:
Post::withoutGlobalScope(PublishedOrderScope::class)->get();
Because global scopes run implicitly, they can affect debugging and reporting queries if forgotten.
You can apply scopes conditionally:
$users = User::when($isActive, fn($query) => $query->active())->get();
$customers = Customer::highValue()->withSum('orders as total_spent', 'amount')->get();
public function scopeWithTrashedOnly($query)
{
return $query->onlyTrashed();
}
Apply tenant constraints:
public function scopeForTenant($query, $tenantId)
{
return $query->where('tenant_id', $tenantId);
}
Scopes rarely cause errors, but common issues include:
To diagnose issues, use:
Model::withoutGlobalScopes()->toSql();
This helps inspect the generated SQL structure, though bindings are not included.
Scopes add no meaningful overhead because they only modify the query builder before SQL execution.
Best practices:
| Feature | Eloquent Scopes | Repositories / Services | Inline Queries |
|---|---|---|---|
| Readability | Excellent | Good | Poor |
| Reusability | High | High | Low |
| Boilerplate | Very Low | Medium | High |
| Complexity | Low | Medium | Low |
Custom Eloquent scopes are one of the most elegant tools in Laravel for organizing query logic. By encapsulating filtering and ordering rules inside your models, scopes promote clarity, reusability, and maintainability throughout your application. Whether you're cleaning up repetitive queries, enforcing consistent constraints, or building complex filtering pipelines, scopes provide a simple and expressive way to write high-quality Laravel code.
If your queries are getting unwieldy or repetitive, it’s time to refactor them using Eloquent scopes—your future self will thank you.