Published on September 05 Aug 25

Stop Writing Repetitive Query Filters in Laravel

1 month ago 62

Stop Writing Repetitive Query Filters in Laravel — Meet YSM/Filterable

In every real-world Laravel project, there comes a time when your controllers start filling up with conditional query logic:

$query->when(request('status'), fn ($q, $status) => $q->where('status', $status));
$query->when(request('category'), fn ($q, $category) => $q->where('category', $category));
$query->when(request('published'), fn ($q) => $q->where('published', true));

It works, sure. But as your filters grow, it gets ugly, repetitive, and hard to test or maintain.

That’s where YSM/Filterable comes in.


🎯 What is YSM/Filterable?

YSM/Filterable is a Laravel package that makes dynamic filtering clean, reusable, and decoupled.

Instead of writing filtering logic inside your controller or query builder, you define all your filters in a dedicated class, keeping your controller logic clean and maintainable.

Think of it as FormRequest but for filtering.


🚀 Installation

Install it via Composer:

composer require ysm/filterable

✍️ Basic Usage Example

Let’s say we have a Post model and we want to filter it by:

  • Title (partial match)

  • Category (exact match)

  • Published status (boolean)

Step 1: Add the Trait to the Model

use YSM\Filterable\Concerns\InteractWithFilterable;

class Post extends Model
{
    use InteractWithFilterable;
}

Step 2: Create a Filter Class

use YSM\Filterable\Filterable;

class PostFilter extends Filterable
{
    protected array $allowedFilters = ['title', 'category', 'published'];

    public function title(string $value): void
    {
        $this->builder->where('title', 'like', "%{$value}%");
    }

    public function category(string $value): void
    {
        $this->builder->where('category', $value);
    }

    public function published(bool $value): void
    {
        $this->builder->where('published', $value);
    }
}

Step 3: Use in Your Controller

public function index()
{
    $posts = Post::filterable(PostFilter::class)->get();
    return response()->json(['data' => $posts]);
}

Now you can hit the endpoint with:

GET /posts?title=Laravel&category=tutorial&published=1

And PostFilter will take care of the rest. Clean and simple.


🧠 What Makes YSM/Filterable Special?

Besides moving filter logic out of your controller, it supports:

✅ Aliases for Request Parameters

Map cat to category, or q to title.

protected array $aliases = ['cat' => 'category'];

✅ Auto-apply Filters (Even Without Request Input)

You can auto-apply filters like:

protected array $autoApplyFilters = ['published'];

This ensures published=true is always applied unless explicitly overridden.


✅ Whitelisting / Blacklisting Filters

Prevent users from filtering on sensitive fields.

protected array $allowedFilters = ['title', 'category'];
protected array $forbiddenFilters = ['created_at'];

✅ Default Values for Filters

Apply fallback filters if no user input is provided:

protected array $defaults = [
    'published' => true,
    'category' => 'blog'
];

✅ Applied Filters Debugging

Want to inspect which filters were actually used?

$filter = PostFilter::make();
$posts = Post::filterable($filter)->get();

$filter->getAppliedFilters();     // ['title' => 'Laravel']
$filter->getConfiguredFilters();  // All internal rules

🧪 Bonus: Testable Filtering Logic

Because your filter logic is in a dedicated class, you can unit test it independently from the controller.

public function test_title_filter_applies_correctly()
{
    Post::factory()->create(['title' => 'Laravel Tips']);
    Post::factory()->create(['title' => 'Vue.js Guide']);

    $filter = PostFilter::make()->withInput(['title' => 'Laravel']);
    $results = Post::filterable($filter)->get();

    $this->assertCount(1, $results);
    $this->assertEquals('Laravel Tips', $results->first()->title);
}

Clean architecture. Clean tests.


🧰 When Should You Use This?

If your app supports search, filtering, or query customization, this package is a must.

Some perfect use cases:

  • Admin dashboards

  • REST APIs with multiple filters

  • Multi-field search in public websites

  • Paginated endpoints with sort/filter logic


📦 Ready to Try It?

The package is open-source and actively maintained.

🔗 GitHub: https://github.com/DevYSM/filterable
📄 MIT License
⚙️ PHP 8.0+ | Laravel 8.x+


💬 Final Thoughts

I created YSM/Filterable to scratch a real itch — filtering was getting messy, repetitive, and hard to maintain. If you feel the same, I invite you to give it a try, and contribute your thoughts or improvements!

Let me know what you think, and feel free to open issues or PRs ❤️

Thanks for reading!

If this helped you, consider giving the repo a ⭐ on GitHub and sharing the package with fellow Laravel developers.

#JavaScript #jQuery #laravel #php #elasticsearch #mongodb #mysql #wordpress #html #css #bootstrap #php8 #ui-development #tailwindcss #postgresql #redis #docker #openai #codewithyassen #ysm #filterable #filter