PHP
Implementing Global Scopes for Application-Wide Eloquent Filtering
Apply consistent query constraints across multiple models automatically using Laravel Eloquent global scopes, ensuring data integrity and simplifying common query patterns.
// 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
{
/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function apply(Builder $builder, Model $model)
{
$builder->where('is_published', true);
}
}
// app/Models/Post.php
namespace App\Models;
use App\Scopes\PublishedScope;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
protected $fillable = ['title', 'content', 'is_published'];
/**
* The "booted" method of the model.
*
* @return void
*/
protected static function booted()
{
static::addGlobalScope(new PublishedScope);
}
}
// app/Models/Page.php
namespace App\Models;
use App\Scopes\PublishedScope;
use Illuminate\Database\Eloquent\Model;
class Page extends Model
{
protected $fillable = ['title', 'body', 'is_published'];
protected static function booted()
{
static::addGlobalScope(new PublishedScope);
}
}
// Usage example (e.g., in a controller)
// Only published posts will be retrieved by default
$publishedPosts = Post::all();
// You can temporarily remove a global scope
$allPostsIncludingUnpublished = Post::withoutGlobalScope(PublishedScope::class)->get();
// Or remove all global scopes
$allPostsIncludingUnpublishedAndMore = Post::withoutGlobalScopes()->get();
// Query on published items
$latestPublishedPost = Post::orderBy('created_at', 'desc')->first();
How it works: Global scopes allow you to add constraints to all queries for a given model. They are ideal for "soft deletes," multi-tenancy, or ensuring only "published" content is retrieved by default. To define one, create a class that implements `Illuminate\Database\Eloquent\Scope` and implement its `apply` method, adding your desired `where` clauses. Then, register the scope within the model's `booted()` method using `static::addGlobalScope()`. You can temporarily remove global scopes for specific queries using `withoutGlobalScope()` or `withoutGlobalScopes()`.