How to add an advanced filter to a model in Laravel

widget

Overview

In this shot, we will use the laravel-eloquent-filters package, which gives you fine-grained control over how you sift smooth models. This package is particularly useful if you want to address complex use-cases, execute sifting on numerous parameters, or utilize complex logic.

Installation

Run the command below:

composer require pricecurrent/laravel-eloquent-filters

Implementation

To use this package on any model, you have to import the Filterable traits, as shown below:

se Pricecurrent\LaravelEloquentFilters\Filterable;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    use Filterable;
}

Examples

Let’s say we have a Product table and we want to filter query results by name.

use App\Filters\NameFilter;
use Pricecurrent\LaravelEloquentFilters\EloquentFilters;

class ProductsController
{
    public function index(Request $request)
    {
        $filters = EloquentFilters::make([new NameFilter($request->name)]);

        $products = Product::filter($filters)->get();
    }
}

We need to generate the NameFilter with an artisan command:

 php artisan eloquent-filter:make NameFilter

You can find the NameFilter in the app/Filters directory.

Here is an example of a NameFilter:

use Pricecurrent\LaravelEloquentFilters\AbstractEloquentFilter;
use Illuminate\Database\Eloquent\Builder;

class NameFilter extends AbstractEloquentFilter
{
    protected $name;

    public function __construct($name)
    {
        $this->name = $name;
    }

    public function apply(Builder $builder): Builder
    {
        return $query->where('name', 'like', "{$this->name}%");
    }
}

This NameFilter can be used by another Eloquent model, which is why it’s not tied to any specific model.

use App\Filters\NameFilter;
use App\Models\User;
use Pricecurrent\LaravelEloquentFilters\EloquentFilters;

class UsersController
{
    public function index(Request $request)
    {
        $filters = EloquentFilters::make([new NameFilter($request->user_name)]);

        $products = User::filter($filters)->get();
    }
}

You can chain methods and treat them as an Eloquent builder.

use App\Filters\NameFilter;
use App\Models\User;
use Pricecurrent\LaravelEloquentFilters\EloquentFilters;

class UsersController
{
    public function index(Request $request)
    {
        $filters = EloquentFilters::make([new NameFilter($request->user_name)]);

        $products = User::query()
            ->filter($filters)
            ->limit(10)
            ->latest()
            ->get();
    }
}

Code explanation

EloquentFilters:: instantiates the package for us and we call make(), and the filters we created that we want to use are passed as an argument. Just like other Eloquent builders, you can now call it on the model you wish to query; you can also chain other Eloquent builders.

Free Resources