PHP
Creating Reusable Query Conditions with Eloquent Local Scopes
Define local query scopes in your Eloquent models to encapsulate common query logic, making your database queries cleaner and more maintainable.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class Product extends Model
{
/**
* Scope a query to only include active products.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeActive(Builder $query)
{
return $query->where('status', 'active');
}
/**
* Scope a query to only include products with stock greater than a given amount.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param int $amount
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeInStock(Builder $query, int $amount = 0)
{
return $query->where('stock', '>', $amount);
}
/**
* Scope a query to include products created recently.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $period e.g., '1 week ago'
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeRecentlyCreated(Builder $query, string $period = '-1 day')
{
return $query->where('created_at', '>=', now()->modify($period));
}
}
// Usage examples:
// Get all active products
$activeProducts = Product::active()->get();
// Get active products with at least 10 items in stock
$availableProducts = Product::active()->inStock(10)->get();
// Get products created in the last 7 days
$newProducts = Product::recentlyCreated('-1 week')->get();
// Combine with other query methods
$filteredProducts = Product::active()->where('price', '<', 50)->get();
How it works: Local scopes allow you to define common sets of constraints that you can easily reuse in your application. By prefixing a method name with `scope` (e.g., `scopeActive`), Eloquent automatically converts it to an executable scope (e.g., `active()`). This snippet demonstrates `scopeActive` for filtering by status, `scopeInStock` for filtering by stock level (with a parameter), and `scopeRecentlyCreated` for time-based filtering. Local scopes make your queries more readable, prevent code duplication, and allow for chaining with other query builder methods, enhancing maintainability.