PHP
Organize Query Logic with Eloquent Local Scopes
Encapsulate and reuse common query constraints across your Laravel Eloquent models by defining and applying local scopes. This promotes cleaner, more maintainable code and improves query readability.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
/**
* Scope a query to only include published posts.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePublished(Builder $query): Builder
{
return $query->where('published_at', '<=', now());
}
/**
* Scope a query to only include posts by a given user.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param int $userId
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeByUser(Builder $query, int $userId): Builder
{
return $query->where('user_id', $userId);
}
}
// --- Usage ---
// Get all published posts
$publishedPosts = App\Models\Post::published()->get();
echo "Published Posts:
";
foreach ($publishedPosts as $post) {
echo "- " . $post->title . "
";
}
// Get all posts published by a specific user (e.g., user ID 1)
$userPublishedPosts = App\Models\Post::published()->byUser(1)->get();
echo "
Published Posts by User 1:
";
foreach ($userPublishedPosts as $post) {
echo "- " . $post->title . "
";
}
// You can also chain multiple scopes
$recentPublishedPosts = App\Models\Post::published()->where('created_at', '>=', now()->subDays(7))->get();
echo "
Recent Published Posts:
";
foreach ($recentPublishedPosts as $post) {
echo "- " . $post->title . "
";
}
How it works: Local scopes allow you to define common sets of query constraints that you can easily reuse throughout your application. A scope method is prefixed with `scope` and accepts the `Illuminate\Database\Eloquent\Builder` instance as its first argument. Any additional arguments are passed directly to the scope method. This pattern makes your Eloquent queries more readable and maintainable by abstracting complex or repetitive `where` clauses into descriptive method calls, which can then be chained with other query builder methods or other scopes.