Laravel Tutorials

Laravel Global Scopes: Automatic Query Filtering

Published
Laravel Global Scopes: Automatic Query Filtering image

Global scopes provide a streamlined way to apply consistent constraints across all queries for specific Eloquent models. Laravel's soft delete feature demonstrates this concept by automatically filtering out deleted records from query results.

Define global scopes by creating classes that implement the Illuminate\Database\Eloquent\Scope interface:

<?php
 
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);
}
}

Apply the scope to your model using the ScopedBy attribute to ensure all queries automatically include the constraint:

<?php
 
namespace App\Models;
 
use App\Models\Scopes\ActiveScope;
use Illuminate\Database\Eloquent\Attributes\ScopedBy;
use Illuminate\Database\Eloquent\Model;
 
#[ScopedBy([ActiveScope::class])]
class Product extends Model
{
protected $fillable = ['name', 'price', 'is_active'];
}

This approach proves invaluable in multi-tenant applications where data isolation is critical. Consider a SaaS platform serving multiple organizations, where each tenant's data must remain completely separated:

<?php
 
namespace App\Models\Scopes;
 
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
 
class TenantScope implements Scope
{
public function apply(Builder $builder, Model $model): void
{
if (auth()->check() && auth()->user()->tenant_id) {
$builder->where('tenant_id', auth()->user()->tenant_id);
}
}
}
 
class PublishedScope implements Scope
{
public function apply(Builder $builder, Model $model): void
{
$builder->where('status', 'published')
->where('published_at', '<=', now());
}
}
 
#[ScopedBy([TenantScope::class, PublishedScope::class])]
class Document extends Model
{
protected $fillable = ['title', 'content', 'status', 'tenant_id', 'published_at'];
 
protected $casts = [
'published_at' => 'datetime',
];
}
 
class DocumentController extends Controller
{
public function index()
{
$documents = Document::orderBy('published_at', 'desc')->get();
 
return view('documents.index', compact('documents'));
}
 
public function adminIndex()
{
$allDocuments = Document::withoutGlobalScopes([PublishedScope::class])
->orderBy('created_at', 'desc')
->get();
 
return view('admin.documents.index', compact('allDocuments'));
}
 
public function systemReport()
{
$systemWideDocuments = Document::withoutGlobalScopes()
->selectRaw('tenant_id, count(*) as document_count')
->groupBy('tenant_id')
->get();
 
return view('reports.system', compact('systemWideDocuments'));
}
}

Global scopes automatically enforce business rules at the model level, ensuring data consistency without requiring manual constraint application in every query. When necessary, you can bypass these constraints using withoutGlobalScope() for specific scopes or withoutGlobalScopes() to remove all applied global filters.

Harris Raftopoulos photo

Senior Software Engineer • Staff & Educator @ Laravel News • Co-organizer @ Laravel Greece Meetup

Sponsored

laravelcloud logo
Laravel Cloud

Easily create and manage your servers and deploy your Laravel applications in seconds.

Visit Laravel Cloud

The latest

View all →
CPX: The Composer Package Executor for PHP image

CPX: The Composer Package Executor for PHP

Read article
Laravel AI SDK Adds Human-in-the-Loop Tool Approval image

Laravel AI SDK Adds Human-in-the-Loop Tool Approval

Read article
Pest 5 Released With Test Impact Analysis, Agent Verification, and Evals image

Pest 5 Released With Test Impact Analysis, Agent Verification, and Evals

Read article
Queue-SQL: Run Mass Deletes and Updates Across Parallel Queue Jobs image

Queue-SQL: Run Mass Deletes and Updates Across Parallel Queue Jobs

Read article
Blade Formatting in Laravel Pint image

Blade Formatting in Laravel Pint

Read article
Inertia DevTools Is Now on the Chrome Web Store image

Inertia DevTools Is Now on the Chrome Web Store

Read article