Skip to main content

Query Scopes and Advanced Queries

11/28
Chapter 3 Eloquent ORM and Database Mastery

Query Scopes and Advanced Queries

20 min read Lesson 11 / 28

Writing Elegant Queries with Scopes

Query scopes encapsulate common query constraints into reusable, chainable methods on your model.

Local Scopes

class Post extends Model
{
    public function scopePublished(Builder $query): Builder
    {
        return $query->where('is_published', true)
                     ->whereNotNull('published_at')
                     ->where('published_at', '<=', now());
    }

    public function scopeFeatured(Builder $query): Builder
    {
        return $query->where('is_featured', true);
    }

    public function scopeByCategory(Builder $query, int $categoryId): Builder
    {
        return $query->where('category_id', $categoryId);
    }

    public function scopeRecent(Builder $query, int $days = 30): Builder
    {
        return $query->where('published_at', '>=', now()->subDays($days));
    }
}

Chaining Scopes

// Clean, readable queries
$posts = Post::published()
    ->featured()
    ->recent(7)
    ->with(['author', 'tags'])
    ->latest('published_at')
    ->paginate(12);

$techPosts = Post::published()
    ->byCategory($techCategory->id)
    ->withCount('comments')
    ->get();

Advanced Query Techniques

Subqueries:

$users = User::addSelect([
    'latest_post_title' => Post::select('title')
        ->whereColumn('user_id', 'users.id')
        ->published()
        ->latest()
        ->limit(1),
])->get();

Conditional Queries:

$posts = Post::published()
    ->when($request->category, fn ($q, $cat) =>
        $q->where('category_id', $cat)
    )
    ->when($request->search, fn ($q, $search) =>
        $q->where('title', 'like', "%{$search}%")
    )
    ->when($request->sort === 'popular', fn ($q) =>
        $q->orderByDesc('views_count'),
        fn ($q) => $q->latest('published_at')
    )
    ->paginate(15);

Chunk Processing for Large Datasets:

Post::where('is_published', true)->chunk(200, function ($posts) {
    foreach ($posts as $post) {
        SearchIndex::update($post);
    }
});

Query scopes transform messy where chains into a domain-specific language that reads like English.