PHP
Reusable Query Logic with Eloquent Scopes
Create reusable local and global query scopes in Laravel Eloquent to encapsulate common query constraints and keep your controllers clean.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
// Local Scope: To retrieve only 'published' products
public function scopePublished(Builder $query): void
{
$query->where('status', 'published')
->where('published_at', '<=', now());
}
// Local Scope with Parameters: To filter by category
public function scopeByCategory(Builder $query, string $categoryName): void
{
$query->whereHas('category', function (Builder $q) use ($categoryName) {
$q->where('name', $categoryName);
});
}
// --- Usage Examples ---
// Get all published products
$publishedProducts = Product::published()->get();
// Get published products in 'Electronics' category
$electronics = Product::published()->byCategory('Electronics')->get();
// You can also chain multiple scopes:
$activePremiumProducts = Product::where('is_active', true)->scopePremium()->get(); // Assuming scopePremium exists
// Global Scope Example (in a Service Provider or model boot method):
// protected static function booted()
// {
// static::addGlobalScope('recent', function (Builder $builder) {
// $builder->orderBy('created_at', 'desc');
// });
// }
// Now, all Product queries will automatically order by created_at desc
// You can remove a global scope for a query: Product::withoutGlobalScope('recent')->get();
}
How it works: Eloquent scopes allow you to define common sets of constraints that can be easily reused throughout your application. Local scopes are methods prefixed with `scope` in your model and can be chained onto any query builder instance. They promote cleaner code by abstracting complex query logic. Global scopes apply to all queries on a given model by default, useful for enforcing application-wide constraints like 'only show active users'. You can temporarily remove global scopes when needed.