Blog Detail

03

Dec
Filtering Eloquent Models in Laravel with Eloquent Filter cover image

arrow_back Filtering Eloquent Models in Laravel with Eloquent Filter

Eloquent Filter is a package for filter data of models by the query strings. This package adds custom filters to your Eloquent models in Laravel. It is easy to use and fully dynamic.

Requirements

  • PHP 7.2+, 8.0 (new version)
  • Laravel 5.8+,6.x,7.x,8(prefer-stable)

Introduction

Let’s say you want to make an advanced search page with multiple filter option params.

A simple implementation without Eloquent Filter

The Request URI could look like this:

http://localhost:8000/users/index?age_more_than=25&gender=male&created_at=25-09-2019

And a simple implementation in the Controller would look like this:

<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;

class UserController extends Controller
{
    public function index(Request $request)
    {
        $users = User::where('is_active', true);

        if ($request->has('age_more_than')) {
            $users->where('age', '>', $request->age_more_than);
        }

        if ($request->has('gender')) {
            $users->where('gender', $request->gender);
        }

        if ($request->has('created_at')) {
            $users->where('created_at','>=', $request->created_at);
        }

        return $users->get();
    }
}

This solution is simple, but that works fine. But you’d have to add a condition for each filter you need. Especially with more complex filtering, your code can become a Monster very fast!

Simple implementation with Eloquent Filter

Eloquent Filter can help you to fix that problem. Just you will set query string to work with that. It will save you time and minimize the complexity of your code.

After installing Eloquent Filter the request URI could look like this:

http://localhost:8000/users/list?age_more_than[operator]=>&age[value]=35&gender=male&created_at[operator]==>&created_at[value]=25-09-2019

And in the controller you’d just need that one line:

/**
 * Class UsersController.
 */

namespace App\Http\Controllers;

use App\User;

class UsersController
{
    public function list()
    {
        return User::filter()->get();
    }
}

With this Eloquent filter implementation, you can use all the documented filters!

Installation

You’ve to run this Composer command to install the latest version of this package:

  $ composer require mehdi-fathi/eloquent-filter

Note for Laravel versions older than 5.8 you should install version 2.2.5

  $ composer require mehdi-fathi/eloquent-filter:2.2.5

Add eloquentFilter\ServiceProvider::class to provider app.php

'providers' => [
  /*
   * Package Service Providers...
   */
    eloquentFilter\ServiceProvider::class
],

Add Facade ‘EloquentFilter’ => eloquentFilter\Facade\EloquentFilter::class to aliases app.php

'alias' => [
  /*
   * Facade alias...
   */
    'EloquentFilter' => eloquentFilter\Facade\EloquentFilter::class,
],

Basic Usage

Config Model and set whitelist

Add The Filterable trait to your models and set fields that you will want to filter in the whitelist array. as well You can override this method in your models.

use eloquentFilter\QueryFilter\ModelFilters\Filterable;

class User extends Model
{
    use Filterable;
    
    private static $whiteListFilter =[
        'id',
        'username',
        'email',
        'created_at',
        'updated_at',
    ];
}

You can set * char for that filter in all fields like the below example:

private static $whiteListFilter = ['*'];

You can add or set $whiteListFilter on the fly in your method. For example:

Set array to WhiteListFilter

Note : This method override $whiteListFilter array

User::setWhiteListFilter(['name']); 

Add a new field to WhiteListFilter

User::addWhiteListFilter('name'); 

Use in Controller

Change your code the controller of the laravel project as like below example:

namespace App\Http\Controllers;

/**
 * Class UsersController.
 */
class UsersController
{

    public function list()
    {
          if (!empty(request()->get('username'))) {
          
              $users = User::ignoreRequest('perpage')->filter()->with('posts')
                        ->orderByDesc('id')->paginate(request()->get('perpage'),['*'],'page');

          } else {
              $users = User::filter(
                ['username' => ['mehdi','ali']]           
                )->with('posts')->orderByDesc('id')->paginate(10,['*'],'page');
          }
    }
}

Note : The Eloquent Filter config by default uses the query string to make queries in Laravel. Although, you can set the array to the filter method Model for making your own custom condition without query string.

Note : Therefore you must unset yourself param as per page. Just you can set page param for paginating this param ignore from the filter.

You can ignore some of the request params by use of the bellow code.

User::ignoreRequest(['perpage'])
            ->filter()
            ->paginate(request()->get('perpage'), ['*'], 'page');

Call ignoreRequest that will ignore some requests that you don’t want to use in conditions eloquent filter. For example, the per-page param will never be in the conditions eloquent filter. it’s related to the paginate method. page param ignores by default in Eloquent Filter of Laravel.

You can filter some of the request params for use in Eloquent Filter.

User::AcceptRequest(['username','id'])
            ->filter()
            ->paginate(request()->get('perpage'), ['*'], 'page');

Call AcceptRequest will accept requests which you want to use in conditions Eloquent Filter. For example, username and id param will be in the conditions eloquent filter. Just notice you must set $whiteListFilter in Model. This method is useful for query string manipulation by a user.

Another example use of a filter eloquent filter.

User::filter()->paginate();
  • EloquentFilter::filterRequests() get all params that used by the Eloquent Filter. You can set key to get specific index. For example EloquentFilter::filterRequests(‘username’) it’s getting username index.

  • EloquentFilter::getAcceptedRequest() get all params that set by the AcceptRequest method.

  • EloquentFilter::getIgnoredRequest() get all ignored params that set by the getIgnoreRequest method.

This package has a lot more advanced options. If you wanna explore them, you can visit its documentation with code examples on Github.

Published at : 03-12-2021

Author : Rizwan Aslam
AUTHOR
Rizwan Aslam

I am a highly results-driven professional with 12+ years of collective experience in the grounds of web application development especially in laravel, native android application development in java, and desktop application development in the dot net framework. Now managing a team of expert developers at Codebrisk.

Launch your project

Launch project