As Laravel applications grow, database queries tend to become repetitive and inconsistent. Conditions like is_active = true, deleted_at IS NULL, or tenant_id = ? start appearing everywhere.
Laravel solves this elegantly with Eloquent Scopes.
In this article, we’ll break down Global Scopes and Local (Custom) Scopes, explain when to use each, and demonstrate production-ready implementations following Laravel’s latest best practices.
What Is an Eloquent Scope?
An Eloquent scope is a way to encapsulate common query constraints inside your model so they can be reused, composed, and maintained centrally.
Laravel provides two types:
Global Scopes – Automatically applied to every query
Local Scopes – Explicitly applied when needed
1. Global Scopes
What Is a Global Scope?
A global scope automatically adds constraints to every query executed against a model.
Typical use cases include:
Soft deletes
Multi-tenancy
Active / published records
Data visibility rules
Creating a Global Scope (Class-Based)
Step 1: Create the Scope Class
php artisan make:scope ActiveScopeStep 2: Implement the Scope
namespace App\Models\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): void
{
$builder->where('is_active', true);
}
}Step 3: Register the Scope on the Model
use App\Models\Scopes\ActiveScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected static function booted(): void
{
static::addGlobalScope(new ActiveScope);
}
}How It Works
Now, every query automatically includes:
WHERE is_active = trueUser::all(); // Only active users
User::find(1); // Only if active
User::count(); // Only activeNo repetition. No mistakes.
Temporarily Disabling a Global Scope
Laravel allows precise control when you need it.
Disable a Specific Scope
User::withoutGlobalScope(ActiveScope::class)->get();Disable All Global Scopes
User::withoutGlobalScopes()->get();This is critical for admin panels, background jobs, or audits.
Anonymous Global Scopes (Quick Use)
For simple rules, Laravel allows inline scopes.
protected static function booted(): void
{
static::addGlobalScope('published', function (Builder $builder) {
$builder->where('published_at', '<=', now());
});
}Use this only when the logic is small and model-specific.
2. Local (Custom) Scopes
What Is a Local Scope?
A local scope is applied only when you explicitly call it.
They’re ideal for:
Reusable filters
Query composition
Readable fluent APIs
Creating a Local Scope
Local scopes are simply model methods prefixed with scope.
Example: scopeActive()
use Illuminate\Database\Eloquent\Builder;
class User extends Model
{
public function scopeActive(Builder $query): Builder
{
return $query->where('is_active', true);
}
}Using the Local Scope
User::active()->get();
User::active()->where('role', 'admin')->get();Laravel removes the scope prefix automatically.
Local Scope with Parameters
Example: scopeRole($role)
public function scopeRole(Builder $query, string $role): Builder
{
return $query->where('role', $role);
}Usage
User::role('manager')->get();
User::active()->role('admin')->get();This makes queries expressive and composable.
Combining Global & Local Scopes
User::active()
->role('editor')
->latest()
->paginate(20);✔ Global scope ensures visibility rules
✔ Local scopes handle business filters
This is the ideal architecture for scalable apps.
Removing Global Scope Inside a Local Scope
Sometimes you want a local scope that bypasses a global rule.
public function scopeWithInactive(Builder $query): Builder
{
return $query->withoutGlobalScope(ActiveScope::class);
}Usage:
User::withInactive()->get();Best Practices (From Real Projects)
✔ Use global scopes for mandatory constraints
✔ Use local scopes for optional filters
✔ Prefer class-based global scopes
✔ Keep scopes query-only (no side effects)
✔ Name scopes clearly and intentionally
When NOT to Use Scopes
❌ Complex business workflows
❌ Authorization decisions
❌ Cross-model orchestration
Scopes are for query constraints, not domain logic.
Final Thoughts
Eloquent scopes are one of Laravel’s most elegant features. When used properly, they:
Eliminate query duplication
Enforce consistency
Improve readability
Scale naturally with your application
If you see the same where() clause repeated more than twice, it’s time for a scope.









