PHP
Apply Universal Query Constraints with Eloquent Global Scopes
Understand how to implement Laravel Eloquent global scopes to automatically apply query constraints across all queries for a specific model, ensuring data consistency.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
// 1. Define a Global Scope Class
// app/Scopes/PublishedScope.php
// namespace App\Scopes;
//
// use Illuminate\Database\Eloquent\Builder;
// use Illuminate\Database\Eloquent\Model;
// use Illuminate\Database\Eloquent\Scope;
//
// class PublishedScope implements Scope
// {
// public function apply(Builder $builder, Model $model)
// ()
// $builder->where('published', true);
// }
// }
// 2. Apply the Global Scope to an Eloquent Model
class Article extends Model
{
protected $fillable = ['title', 'content', 'published'];
protected static function booted()
{
static::addGlobalScope('published', function (Builder $builder) {
$builder->where('published', true);
});
// Alternative: Using a dedicated scope class
// static::addGlobalScope(new \App\Scopes\PublishedScope);
}
// You can remove global scopes temporarily if needed
public function getAllArticles()
{
return static::withoutGlobalScope('published')->get();
}
}
// Example Usage:
// Assume some articles are published = true, some published = false
// This will only return articles where 'published' is true due to the global scope
$publishedArticles = App\Models\Article::all();
// To get all articles, including unpublished ones, temporarily remove the scope
$allArticles = App\Models\Article::withoutGlobalScope('published')->get();
// If using a dedicated class, you can remove it by class name:
// $allArticlesFromClass = App\Models\Article::withoutGlobalScope(\App\Scopes\PublishedScope::class)->get();
echo "Published articles count: " . $publishedArticles->count() . "
";
echo "All articles count (without scope): " . $allArticles->count() . "
";
How it works: Eloquent Global Scopes allow you to automatically apply a query constraint to *all* queries executed against a given model. This is incredibly useful for ensuring data consistency, such as always fetching only 'published' records or filtering by a tenant ID in a multi-tenant application. You can define global scopes directly within the model's `booted()` method or in dedicated scope classes. While active by default, global scopes can be temporarily removed using `withoutGlobalScope()` when a specific query requires bypassing the constraint.