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

Subscribe to the newsletter

Get new articles and course lessons delivered to your inbox. No spam, unsubscribe anytime.

© 2026 Mahamudul Hasan Rubel. All rights reserved.

Built with using Next.js 16 & Tailwind v4

Back to Blog
Lesson 21 of the Intermediate Laravel: Real-World Application Patterns course
LaravelJune 26, 20263 min read

Advanced Request Filtering and Sorting in Laravel APIs

Master advanced filtering, sorting, and pagination in Laravel to build scalable APIs. Learn to parse query params and implement dynamic Eloquent queries today.

LaravelAPIEloquentPaginationRefactoringphpbackend

Previously in this course, we explored Advanced Eloquent Scopes and Accessors: Cleaner Laravel Models to keep our database logic expressive. In this lesson, we are taking that foundation and applying it to our API layer, specifically addressing how to handle filtering, sorting, and pagination dynamically.

When building a project board API, you eventually reach a point where clients need to search for tasks by status, sort them by priority, or fetch them in manageable chunks. Hard-coding these paths is a maintenance nightmare. Instead, we’ll build a dynamic query pipeline.

The Problem: Controller Bloat

If you’ve ever seen a controller method with a dozen if ($request->has(...)) statements, you know the pain. Not only is it hard to read, but it’s also impossible to reuse.

To solve this, we will use a "Pipeline" approach. We want our controller to look like this:

PHP
public function index(Request $request)
{
    $tasks = $this->taskService->search($request->all());
    return TaskResource::collection($tasks);
}

By delegating the logic to the TaskService (following our work in Implementing the Service Layer), we keep our API endpoints thin and maintainable.

Building the Query Pipeline

1. Handling Filtering

We’ll leverage the Eloquent scopes we defined earlier. To make this dynamic, we map incoming request keys to specific scope methods.

PHP
#6A9955">// Inside TaskRepository.php
public function applyFilters(Builder $query, array $filters)
{
    #6A9955">// Map request keys to our model scopes
    if (isset($filters['status'])) {
        $query->whereStatus($filters['status']);
    }

    if (isset($filters['priority'])) {
        $query->wherePriority($filters['priority']);
    }

    return $query;
}

2. Implementing Dynamic Sorting

Sorting is often dangerous if you simply pass user input directly into orderBy(), as it opens the door to SQL injection or exposing sensitive columns. Always use an allow-list.

PHP
public function applySorting(Builder $query, string $sort = null)
{
    $allowedSorts = ['created_at', 'priority', 'due_date'];
    
    #6A9955">// Default to created_at if not provided or invalid
    $column = in_array($sort, $allowedSorts) ? $sort : 'created_at';
    
    return $query->orderBy($column, 'desc');
}

3. Combining with Pagination

Laravel’s paginate() method is the standard for API responses. By combining our filters and sorting before calling paginate, we ensure the query is executed efficiently by the database rather than in memory.

PHP
#6A9955">// TaskRepository.php
public function getFilteredTasks(array $params)
{
    $query = Task::query();

    $this->applyFilters($query, $params);
    $this->applySorting($query, $params['sort'] ?? null);

    return $query->paginate($params['per_page'] ?? 15);
}

Worked Example: Connecting the Layers

In our running project board, let's update the TaskService to handle these incoming parameters.

PHP
#6A9955">// TaskService.php
public function listTasks(array $data)
{
    #6A9955">// We pass the data directly to the repository
    #6A9955">// The repository handles the heavy lifting of Eloquent composition
    return $this->taskRepository->getFilteredTasks($data);
}

This approach allows your API to handle requests like GET /api/tasks?status=in-progress&sort=priority&per_page=50 effortlessly.

Hands-on Exercise

  1. Define an allow-list: In your TaskRepository, create a constant ALLOWED_SORT_COLUMNS to hold the fields users are permitted to sort by.
  2. Refactor: Move your current TaskController logic into the TaskRepository using the pattern shown above.
  3. Test: Write a feature test that sends a request with ?status=completed&sort=due_date and asserts that the returned JSON collection is correctly filtered and sorted.

Common Pitfalls

  • Ignoring Pagination: Always set a default per_page value. Allowing users to fetch thousands of records without limit will eventually crash your memory or slow your database to a crawl.
  • Trusting User Input: Never pass a raw string from $request->get('sort') directly into an orderBy() call. Always validate it against an allow-list.
  • N+1 Queries: Since we are returning a JsonResource collection, ensure you are eager loading relationships (like user or project) within your repository using $query->with(['user']) before calling paginate().

Recap

We’ve evolved from manual request parsing to a clean, service-oriented approach. By centralizing filtering, sorting, and pagination in the repository layer, we’ve made our API more resilient and significantly easier to test. Remember: keep your controllers thin, validate your sorting keys, and always paginate your results.

Up next: We will implement Job Chaining and Batching to handle complex, multi-step background processes for our project tasks.

Previous lessonAPI Versioning StrategiesNext lesson Handling File Uploads in REST APIs
Back to Blog

Similar Posts

LaravelJune 28, 20264 min read

Advanced Eloquent Scopes: Building Complex, Reusable Query Filters

Master advanced Eloquent scopes to encapsulate complex business logic, chain query filters, and maintain clean, expressive models in your Laravel SaaS platform.

Read more
LaravelJune 25, 20263 min read

Task Manager: Completing CRUD Functionality in Laravel

Finalize your Task Manager CRUD functionality by implementing secure edit and delete features. Learn how to maintain data integrity in your Laravel application.

Part of the course

Intermediate Laravel: Real-World Application Patterns

intermediate · Lesson 21 of 58

  1. 1

    Architecting for Maintainability

    3 min
  2. 2

    Implementing the Service Layer

    3 min
  3. 3

    Repository Pattern Fundamentals

    3 min
Read more
LaravelJune 28, 20264 min read

Advanced API Versioning Strategies: Header-Based Routing in Laravel

Master API versioning and maintain backward compatibility in your distributed systems. Learn to implement header-based versioning for clean, scalable APIs.

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

    3 min
  • 14

    Asynchronous Processing with Queues

    4 min
  • 15

    Job Chaining and Batching

    3 min
  • 16

    Feature Testing Fundamentals

    4 min
  • 17

    Mocking Services and Repositories in Tests

    3 min
  • 18

    Testing Events and Jobs

    3 min
  • 19

    Database Factories and Seeding

    3 min
  • 20

    API Versioning Strategies

    4 min
  • 21

    Advanced Request Filtering and Sorting

    3 min
  • 22

    Handling File Uploads in REST APIs

    3 min
  • 23

    Real-time Notifications with Broadcasting

    3 min
  • 24

    Using Observers for Model Lifecycle Hooks

    3 min
  • 25

    Implementing Policies for Authorization

    3 min
  • 26

    Customizing Authentication Guards

    3 min
  • 27

    Rate Limiting API Endpoints

    4 min
  • 28

    Eloquent Performance Optimization

    4 min
  • 29

    Caching Strategies for Performance

    4 min
  • 30

    Using Traits for Code Reuse

    3 min
  • 31

    Advanced Dependency Injection with Service Providers

    3 min
  • 32

    Command Line Tools with Artisan

    3 min
  • 33

    Scheduled Tasks and Cron Jobs

    3 min
  • 34

    Integrating Third-Party Services

    3 min
  • 35

    Handling Webhooks

    3 min
  • 36

    Logging and Monitoring

    3 min
  • 37

    Database Migrations Best Practices

    3 min
  • 38

    Advanced Testing: Integration Tests

    4 min
  • 39

    Testing API Authentication

    4 min
  • 40

    Code Quality and Static Analysis

    3 min
  • 41

    Project Structure for Large Applications

    3 min
  • 42

    Environment and Configuration Management

    3 min
  • 43

    Deploying Laravel Applications

    4 min
  • 44

    Database Indexing Strategies

    4 min
  • 45

    Using Value Objects

    4 min
  • 46

    Strategy Pattern for Business Rules

    3 min
  • 47

    Advanced Queue Monitoring

    3 min
  • 48

    Building a Search API

    3 min
  • 49

    Handling Concurrency and Race Conditions

    4 min
  • 50

    API Documentation with OpenAPI

    3 min
  • 51

    Testing with Test Doubles

    3 min
  • 52

    Implementing Multi-Tenancy

    4 min
  • 53

    Refactoring Legacy Code

    4 min
  • 54

    Using Middleware for Feature Flags

    3 min
  • 55

    Building Reusable Packages

    4 min
  • 56

    Performance Profiling

    3 min
  • 57

    Secure API Design

    3 min
  • 58

    Event Sourcing Concepts

    4 min
  • View full course