Mahamudul Hasan Rubel
HomeBlogCoursesAboutProjectsSkillsExperiencePhotosContact
Mahamudul Hasan Rubel

Senior Software Engineer crafting high-performance web applications and SaaS platforms.

Navigation

  • Home
  • Blog
  • Courses
  • About
  • Projects
  • Skills
  • Experience
  • Photos
  • Contact

Get in Touch

Available for senior/lead roles and consulting.

bd.mhrubel@gmail.comHire Me

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 5 of the Intermediate Laravel: Real-World Application Patterns course
LaravelJune 25, 20264 min read

Advanced Eloquent Scopes and Accessors: Cleaner Laravel Models

Master Eloquent query scopes and accessors to write reusable, expressive database logic. Learn to clean up your controllers by shifting data handling to models.

laraveleloquentquery-scopesaccessorsmodelsrefactoringphpbackend

Previously in this course, we covered Project Board Domain Modeling, where we established the relationships between users, projects, and tasks. Now that our schema is in place, we need to ensure our interaction with this data remains maintainable as the project grows.

In this lesson, we’re moving beyond basic CRUD. We’ll focus on how to use eloquent features to keep our domain logic expressive and our controllers thin. By leveraging query scopes and accessors, we stop repeating filtering logic and data formatting across our services and controllers.

Encapsulating Logic with Query Scopes

A common pain point in growing applications is the repetition of database constraints. If you find yourself writing ->where('status', 'completed') in five different controllers, you’ve created a maintenance burden. If the definition of "completed" changes, you have to hunt down every instance.

Query scopes allow you to define these constraints as reusable methods on your model.

Implementing Local Scopes

A local scope is defined by prefixing a method name with scope. Laravel automatically handles the translation, so calling Task::completed() triggers scopeCompleted().

PHP
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class Task extends Model
{
    #6A9955">/**
     * Scope a query to only include completed tasks.
     */
    public function scopeCompleted(Builder $query): Builder
    {
        return $query->where('status', 'completed');
    }

    #6A9955">/**
     * Scope a query to only include tasks due soon.
     */
    public function scopeDueSoon(Builder $query): Builder
    {
        return $query->where('due_date', '<=', now()->addDays(3))
                     ->where('status', '!=', 'completed');
    }
}

Now, instead of writing raw where clauses, your service layer reads like English:

PHP
#6A9955">// Clean, expressive, and easily testable
$upcomingTasks = Task::dueSoon()->get();

As discussed in Mastering Laravel Local Scopes for Cleaner Database Filtering, these methods are chainable, allowing you to build complex queries dynamically without bloating your controller.

Transforming Data with Accessors and Mutators

While scopes handle retrieval, accessors and mutators handle data transformation. An accessor transforms a value when it is retrieved from the database, while a mutator modifies it before it is saved.

Custom Accessors

Let's say our Task model has a title column, but we want to ensure it’s always returned in title case when accessed via our API.

PHP
use Illuminate\Database\Eloquent\Casts\Attribute;

protected function title(): Attribute
{
    return Attribute::make(
        get: fn(string $value) => ucfirst($value),
    );
}

This is particularly useful for formatting dates, concatenating name fields, or calculating values on the fly. If you want to dive deeper into these patterns, Laravel Eloquent Accessors and Mutators: A Practical Guide provides a comprehensive look at the modern Attribute syntax introduced in recent Laravel versions.

Mutators for Data Integrity

Mutators ensure data is sanitized before it hits the database. If we want to ensure all task titles are stored in lowercase to allow for case-insensitive searching, we add a set method to our attribute definition:

PHP
protected function title(): Attribute
{
    return Attribute::make(
        get: fn(string $value) => ucfirst($value),
        set: fn(string $value) => strtolower($value),
    );
}

Hands-on Exercise

  1. Open your Task model.
  2. Create a scopeOverdue method that filters tasks where the due_date is in the past and the status is not 'completed'.
  3. Implement an accessor for a is_overdue attribute that returns a boolean based on the due_date.
  4. Use these in a temporary route to verify that Task::overdue()->get() returns the correct items and $task->is_overdue works as expected.

Common Pitfalls

  • Over-engineering: Don't turn every simple where clause into a scope. Only create scopes for logic you actually reuse or that significantly improves readability.
  • Performance: Remember that scopes are just query builder modifications. They don't execute the query themselves. Always ensure you are mindful of indexes on the columns you are filtering by.
  • Accessor Side Effects: Never perform heavy operations (like external API calls) inside an accessor. Accessors run every time you touch the property; you don't want to trigger a network request every time you access a field in a loop.

Recap

By moving database constraints into query scopes and data formatting into accessors, we keep our business logic encapsulated within the model. This makes our controllers cleaner and ensures that our data handling rules are applied consistently across the entire application.

Up next: We will implement the TaskService to handle complex task creation logic and manage user-task assignments, tying these model improvements into a cohesive service layer.

Previous lessonProject Board Domain ModelingNext lesson Service-Oriented Task Management
Back to Blog

Similar Posts

LaravelPHPJune 24, 20264 min read

Eloquent custom casts: A Beginner’s Guide to Transforming Data

Eloquent custom casts let you clean up your Laravel models by automatically transforming data. Learn how to handle complex types without the boilerplate.

Read more
LaravelPHPJune 24, 2026

Part of the course

Intermediate Laravel: Real-World Application Patterns

intermediate · Lesson 5 of 58

  1. 1

    Architecting for Maintainability

    3 min
  2. 2

    Implementing the Service Layer

    3 min
  3. 3

    Repository Pattern Fundamentals

    3 min
4 min read

Mastering Laravel Eloquent Model State: exists and wasRecentlyCreated

Mastering Laravel Eloquent model state with exists and wasRecentlyCreated helps you handle database records reliably. Learn to distinguish new from old.

Read more
LaravelPHPJune 23, 20264 min read

Mastering Laravel Local Scopes for Cleaner Database Filtering

Mastering Laravel local scopes helps you write cleaner, more readable database queries. Learn how to encapsulate filtering logic directly within your models.

Read more
  • 4

    Project Board Domain Modeling

    3 min
  • 5

    Advanced Eloquent Scopes and Accessors

    4 min
  • 6

    Service-Oriented Task Management

    3 min
  • 7

    REST API Fundamentals with Sanctum

    3 min
  • 8

    Resource Controllers and API Responses

    3 min
  • 9

    Handling API Validation and Form Requests

    3 min
  • 10

    Implementing Middleware for API Security

    4 min
  • 11

    Database Transactions for Data Integrity

    3 min
  • 12

    Error Handling and Global Exceptions

    3 min
  • 13

    Introduction to Laravel Events and Listeners

    Coming soon
  • 14

    Asynchronous Processing with Queues

    Coming soon
  • 15

    Job Chaining and Batching

    Coming soon
  • 16

    Feature Testing Fundamentals

    Coming soon
  • 17

    Mocking Services and Repositories in Tests

    Coming soon
  • 18

    Testing Events and Jobs

    Coming soon
  • 19

    Database Factories and Seeding

    Coming soon
  • 20

    API Versioning Strategies

    Coming soon
  • 21

    Advanced Request Filtering and Sorting

    Coming soon
  • 22

    Handling File Uploads in REST APIs

    Coming soon
  • 23

    Real-time Notifications with Broadcasting

    Coming soon
  • 24

    Using Observers for Model Lifecycle Hooks

    Coming soon
  • 25

    Implementing Policies for Authorization

    Coming soon
  • 26

    Customizing Authentication Guards

    Coming soon
  • 27

    Rate Limiting API Endpoints

    Coming soon
  • 28

    Eloquent Performance Optimization

    Coming soon
  • 29

    Caching Strategies for Performance

    Coming soon
  • 30

    Using Traits for Code Reuse

    Coming soon
  • 31

    Advanced Dependency Injection with Service Providers

    Coming soon
  • 32

    Command Line Tools with Artisan

    Coming soon
  • 33

    Scheduled Tasks and Cron Jobs

    Coming soon
  • 34

    Integrating Third-Party Services

    Coming soon
  • 35

    Handling Webhooks

    Coming soon
  • 36

    Logging and Monitoring

    Coming soon
  • 37

    Database Migrations Best Practices

    Coming soon
  • 38

    Advanced Testing: Integration Tests

    Coming soon
  • 39

    Testing API Authentication

    Coming soon
  • 40

    Code Quality and Static Analysis

    Coming soon
  • 41

    Project Structure for Large Applications

    Coming soon
  • 42

    Environment and Configuration Management

    Coming soon
  • 43

    Deploying Laravel Applications

    Coming soon
  • 44

    Database Indexing Strategies

    Coming soon
  • 45

    Using Value Objects

    Coming soon
  • 46

    Strategy Pattern for Business Rules

    Coming soon
  • 47

    Advanced Queue Monitoring

    Coming soon
  • 48

    Building a Search API

    Coming soon
  • 49

    Handling Concurrency and Race Conditions

    Coming soon
  • 50

    API Documentation with OpenAPI

    Coming soon
  • 51

    Testing with Test Doubles

    Coming soon
  • 52

    Implementing Multi-Tenancy

    Coming soon
  • 53

    Refactoring Legacy Code

    Coming soon
  • 54

    Using Middleware for Feature Flags

    Coming soon
  • 55

    Building Reusable Packages

    Coming soon
  • 56

    Performance Profiling

    Coming soon
  • 57

    Secure API Design

    Coming soon
  • 58

    Event Sourcing Concepts

    Coming soon
  • View full course