Create AWESOME code snippets and share them with the world in seconds!

X

Laravel Pipeline: Clean & Powerful Query Filtering

Published on July 13, 2025 by

Laravel Pipeline: Clean & Powerful Query Filtering

Laravel Pipeline: Clean & Powerful Query Filtering

In modern Laravel applications, data filtering often becomes messy as requirements grow. From searching by a keyword, to sorting, to filtering by authors — controllers can quickly become cluttered with if and when() helper conditions.

Laravel’s Pipeline provides a powerful, elegant way to manage this complexity. By sending your query through a series of independent filters, you achieve a clean, testable, and highly maintainable solution.


Why Laravel Pipeline?

Let’s say you have this classic scenario:

if ($request->has('title')) {
$query->where('title', 'like', ...);
}
if ($request->has('sort')) {
$query->orderBy(...);
}
// and more...

As new filters are added, these blocks become harder to manage. The Pipeline pattern instead allows you to split each filter into its own class, run them in sequence, and keep your controller clean.


Pipeline in Action

Here’s an example from a real-world controller:

<?php
 
declare(strict_types=1);
 
namespace App\Http\Controllers\Api\V1;
 
use App\Filters\SortFilter;
use App\Filters\TypeFilter;...
use App\Filters\CategoryFilter;
use App\Models\Post as Article;
use Illuminate\Http\JsonResponse;
use App\Filters\SearchByTitleFilter;
use App\Http\Controllers\Controller;
use App\Filters\UsernameAuthorFilter;
use App\Http\Resources\ArticleResource;
use Illuminate\Support\Facades\Pipeline;
use App\Http\Requests\Api\V1\ArticleFilterRequest;
use Symfony\Component\HttpFoundation\Response as HttpResponse;
 
final class ArticleController extends Controller
{
public function index(ArticleFilterRequest $request): JsonResponse
{
$request->validated();
 
$query = Article::query()
->with(['author', 'categories', 'likes'])
->select('posts.*');
 
$pipes = [
SearchByTitleFilter::class,
SortFilter::class,
UsernameAuthorFilter::class,
TypeFilter::class,
CategoryFilter::class,
];
 
$articles = Pipeline::send($query)
->through($pipes)
->thenReturn()
->visible()
->paginate($request->get('per_page'));
 
return response()
->json([
'status' => HttpResponse::HTTP_OK,
'message' => 'Articles retrieved successfully.',
'data' => ArticleResource::collection($articles),
'meta' => [ ...
'current_page' => $articles->currentPage(),
'last_page' => $articles->lastPage(),
'per_page' => $articles->perPage(),
'total' => $articles->total(),
'from' => $articles->firstItem(),
'to' => $articles->lastItem(),
'next_page_url' => $articles->nextPageUrl(),
'prev_page_url' => $articles->previousPageUrl(),
],
], HttpResponse::HTTP_OK);
}
}

The given code was from Laranepal while working on apis for articles.

What’s happening here?

  • ✅ You define a base query
  • ✅ You list your filtering classes (pipes)
  • ✅ The pipeline sends the query through each pipe
  • ✅ You receive the final filtered query for pagination

This pattern removes dozens of if statements and replaces them with reusable, testable filters.


Example Filter Class

For example, your SearchByTitleFilter might look like this:

<?php
 
declare(strict_types=1);
 
namespace App\Filters;
 
use Closure;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Builder;
 
final readonly class SearchByTitleFilter
{
public function __construct(private Request $request) {}
 
public function handle(Builder $builder, Closure $next)
{
return $next($builder)
->when(
$this->request->has('search'),
fn ($query) => $query->where('title', 'REGEXP', $this->request->search)
);
}
}

Each filter is small, focused, and reusable. Adding a new filter only means creating another class and adding it to the pipeline.


Benefits of Laravel Pipeline

  • ✅ Cleaner controllers — avoid bloated logic
  • ✅ Single Responsibility — each filter class handles one task
  • ✅ Testable — filters can be unit-tested in isolation
  • ✅ Extensible — new filters can be added or removed easily
  • ✅ Consistent — data always flows through predictable steps

Learn More

Laravel documents the pipeline helper here: 👉 Laravel Pipeline Documentation

Pipelines aren’t limited to queries — you can use them for data transformations, business logic, or even request handling. They’re an underused yet powerful feature in any Laravel toolbox.


Conclusion

Laravel’s Pipeline pattern is a clean, scalable solution to query filtering. It keeps your controllers lean, promotes separation of concerns, and makes your codebase easier to test and maintain. If you’re building APIs with complex filtering, start leveraging pipelines today — your future self (and your teammates) will thank you!


Dinesh Uprety

Senior Software Engineer • Writer @ Laranepal • PHP, Laravel, Livewire, TailwindCSS & VueJS • CEO @ Laranepal & Founder @ laracodesnap

Filed in:

Discussion

Login or register to comment or ask questions

Shivaji ChaliseShivaji Chalise

neat !

SPONSORED
Codesnap

Codesnap

Create AWESOME code snippets and share them with the world in seconds!