Laravel Filtering Query using Pipelines with Example

When building something in the laravel framework, your application might require filtering query results dynamically based on the user’s request parameters.

This tutorial will demonstrate the process of filtering query results using pipelines while keeping your code clean and readable.

Understanding Laravel Pipeline

Pipeline is a design pattern in OOP specifically designed for handling complex mutation of an object where the object is passed through each task (such as passing a pipe) and returns the final transformed object after executing all tasks.

In other words, the laravel pipeline breaks down the huge complex processes of manipulating objects into smaller individual pieces that are responsible for processing and passing data to the next step. As a result, the code becomes easier to maintain and reusable.

Basic approach to filtering query

Let’s imagine a situation where we are not aware of pipelines, we would normally consider setting up a controller and filter query using conventional if statement.

class PostController
{
    public function index(Request $request)
    {
        $query = Post::query();

        if ($request->has('status')) {
            $query->where('status', $request->status);
        }

        if ($request->has('orderBy')) {
           $query->orderBy('created_at, $request->orderBy);
        }

        // And probably all other filters

        $posts = $query->get();

        return view('post.index', compact('posts'));
    }
}

Although this approach might do the job, this will get messy pretty quickly if you have longer multiple conditions.

Filtering Query using Pipelines

This implementation has a major advantage over the approach previously stated above, its ability to handle an ever-growing number of conditions without compromising the code maintainability.

So, let’s try to refactor the if statement approach mentioned above using pipelines.


Creating a Filter Class

First, in order for pipelines to work, we need to create a filter class. So, let’s create a custom filter class inside app/QueryFilters directory.

Next, Our filter class should have a handle method that contains the logic to filter the query.

# app/QueryFilters/Status.php

<?php

namespace App\QueryFilters;

class Status
{
    public function handle($query, $next)
    {
        if (request()->has('status')) {
            $query->where('status', request('status'));
        }

        $next($builder);
    }
}

This handle method will receive two parameters, the first object is what we pass through our pipeline and the second is a closure function that will move forward to our next filter.

Using Pipeline in our Controller

Pipeline ships with laravel so you don’t need to install any package. Therefore, we simply import Illuminate\Pipeline\Pipeline and instantiate using app().

use Illuminate\Pipeline\Pipeline;

class PostController
{
    public function index(Request $request)
    {
        $query = Post::query();

        $posts = app(Pipeline::class)
                ->send($query)
                ->through([
                    \App\QueryFilters\Status::class,
                    \App\QueryFilters\OrderBy::class,
                ])
                ->thenReturn()
                ->get();

        return view('post.index', compact('posts'));
    }
}
  • The send() method receives the actual object to send through the pipelines.
  • The through() method receives array of filters (known as pipes).
  • The thenReturn() method runs the pipeline and returns the result (which will return the inital query object).

In conclusion

Laravel pipeline gives you a very flexible approach to filtering queries. Whether deciding to use it or not depends upon the complexity of your project, but this short tutorial will give you an idea to make good use of pipelines.

I hope this has been informative and gives you an understanding of how to use laravel pipelines. You can check out more about pipelines and how it works at laravel official docs.

Total
15
Shares
3 comments
  1. Thanks for the comment. That is also one way to do it but I think it’ll soon get convoluted after it reaches multiple numbers of checks. Hence, Pipeline to the rescue. 🙂

  2. This approach looks clean indeed but I wonder if it will work with the Yajra Datatables package, specially using server-side option, as the solution is returning data with ->get().

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Posts
Total
15
Share