AppDividend
Latest Code Tutorials

How To Create Filters In Laravel

Laravel 5.6 Filters

1,714

Get real time updates directly on you device, subscribe now.

In this tutorial, we will see How To Create Filters In Laravel. I will show you how you can filter your data based on the type and categories. If you are making an E-Commerce type of website, then Product Filtering is the essential part of your application. So, we will see, how we can go for Filters in Laravel.

Create Filters In Laravel

As usual, we start our project by installing the Laravel 5.6.

Step 1: Install Laravel.

I am using Laravel Valet, so I can install using the following command.

laravel new filters

If you are not using Valet, then you can pull it through the following command.

composer create-project laravel/laravel filters --prefer-dist

Go into that project.

cd filters

Open the project in your editor; I am using VSCode.

code .

Now, set up the database in your .env file.

Step 2: Create migration and dummy data.

Now, we are filtering products based on type and categories. So let us create the Product model and migration. So generate via the following command.

php artisan make:model Product -m

So it will create both model and migration file.

Inside create_products_table.php file, write the following schema in it.

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('slug');
            $table->enum('type', ['Simple', 'Grouped', 'Variable', 'Gift']);                        
            $table->enum('categories', ['Electronics', 'Books', 'Games', 'Garden']);                                             
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

Migrate all the tables in the database using the following command.

php artisan migrate

Okay, next step is to generate the fake data using the factory. So create a factory using the following command.

php artisan make:factory ProductFactory --model=Product

It will create a file inside database  >>  factories folder called ProductFactory.php.

<?php

use Faker\Generator as Faker;

$factory->define(App\Product::class, function (Faker $faker) {
    return [
        'name' => $name = $faker->sentence,
        'slug' => str_slug($name),
        'type' => ['Simple', 'Grouped', 'Variable', 'Gift'][rand(0,3)],
        'categories' => ['Electronics', 'Books', 'Games', 'Garden'][rand(0,3)],   
    ];
});

So, we have written the code for Factory to generate the random data. It is time to create the data from the factory. There are plenty of ways you can do that, but I prefer the tinker console. Go to your terminal and type the following command.

php artisan tinker

Now, write the following code to generate the data.

factory(\App\Product::class, 20)->create()

See the products table inside the database.

How To Create Filters In Laravel

 

Step 3: Create an endpoint.

Next step is to create a ProductController file. So type the following command.

php artisan make:controller ProductController

Define index method inside that ProductController.php file.

<?php

// ProductController.php

namespace App\Http\Controllers;

use App\Product;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    public function index()
    {
        return Product::get();
    }
}

Define the route inside the web.php file.

Related Posts
1 of 37
Route::get('/products', 'ProductController@index')->name('products');

So, now go to the /products path, and in my case it is http://filter.test/products

Your path might have http://localhost:8000/products 

You can see that; we can get the JSON data of from our database. Now, we need to apply the filter to that data.

Step 4: Create a filter.

 Now, create a Filters folder inside app directory.

In that folder, create one file called TypeFilter.php.

<?php

// TypeFilter.php

namespace App\Filters;

class TypeFilter
{
    public function filter()
    {
            
    }
}

This TypeFilter class is responsible for filtering the data based on the type.

We pass the type in the query string, and according to that, we get out the result. We code this function later.

Now, inside ProductController.php file, we can write the following code.

<?php

// ProductController.php

namespace App\Http\Controllers;

use App\Product;
use Illuminate\Http\Request;

class ProductController extends Controller
{
    public function index(Request $request)
    {
        return Product::filter($request)->get();
    }
}

Inside Filters folder, create one abstract class called AbstractFilter.php.

<?php

// AbstractFilter.php

namespace App\Filters;

use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Builder;

abstract class AbstractFilter
{
    protected $request;

    protected $filters = [];

    public function __construct(Request $request)
    {
        $this->request = $request;
    }
    public function filter(Builder $builder)
    {   
        
    }
}

The only reason I have taken above class as an abstract class because, in the future, we have more than one kind of filters, so It is better to use this class as an abstract and then different filter class can extend this class. So that we do not repeat each code every time.

Next step is to create a new file called ProductFilter.php inside Filters directory.

In this file, we will define the actual filter class.  For this example, I am only using type filter, but you have more than one filter like age, demographics, price, etc.

<?php

// ProductFilter.php

namespace App\Filters;

use App\Filters\AbstractFilter;
use Illuminate\Database\Eloquent\Builder;

class ProductFilter extends AbstractFilter
{
    protected $filters = [
        'type' => TypeFilter::class
    ];
}

Here, I am creating one filter function inside Product modelPass the whole request as a parameter.

<?php

namespace App;

use App\Filters\ProductFilter;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class Product extends Model
{
    public function scopeFilter(Builder $builder, $request)
    {
        return (new ProductFilter($request))->filter($builder);
    }
}

So, now our final file will be AbstractFilter.php looks like this.

<?php

// AbstractFilter.php

namespace App\Filters;

use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Builder;

abstract class AbstractFilter
{
    protected $request;

    protected $filters = [];

    public function __construct(Request $request)
    {
        $this->request = $request;
    }
    public function filter(Builder $builder)
    {   
        foreach($this->getFilters() as $filter => $value)
        {
            $this->resolveFilter($filter)->filter($builder, $value);
        }
        return $builder;
    }

    protected function getFilters()
    {
        return array_filter($this->request->only(array_keys($this->filters)));
    }

    protected function resolveFilter($filter)
    {
        return new $this->filters[$filter];
    }
}

And finally, we write the main filter code inside TypeFilter.php file.

<?php

// TypeFilter.php

namespace App\Filters;

class TypeFilter
{
    public function filter($builder, $value)
    {
        return $builder->where('type', $value);
    }
}

Step 5: Explanation

I will give you the brief explanation of what I have done to achieve the filtered result.

First, to our Filtered page’s URL looks like this: http://filter.test/products?type=Gift

So, the query string is type=Gift. So type is the key and Gift is value. That is why we have created a filter called TypeFilter.php.

Now, we are mapping that type to TypeFilter.php class inside ProductFilter.php file.

So from the ProductController’s index function, we are calling model’s filter function and pass the request as an argument.

Now, inside Product model, we are calling the ProductFilter’s filter method and pass the Eloquent query builder as an argument.

Next, ProductFilter does not have directly filter method, but it is extending the AbstractFilter class, which has the filter method.  So we can use that filter method.

But, that ProductFilter has an array of Filters. In our case, it is just TypeFilter, but there are more filters in real-time web applications.

Next step is inside AbstractFilter.php file; we are calling the filter function.

So first, we are iterating the filters and map the query string key to that filter, if both are matched we directly instantiate that matched class and call that matched class’s method and pass that query string’s key as an argument.

// AbstractFilter.php

public function filter(Builder $builder)
    {   
        foreach($this->getFilters() as $filter => $value)
        {
            $this->resolveFilter($filter)->filter($builder, $value);
        }
        return $builder;
    }

    protected function getFilters()
    {
        return array_filter($this->request->only(array_keys($this->filters)));
    }

    protected function resolveFilter($filter)
    {
        return new $this->filters[$filter];
    }

So, the type is associated with TypeFilter.

That is why TypeFilter.php file’s filter method is called, and it gets a $builder and query string’s value as an argument. In our case value is Gift.

So, it returns only the rows that contain type = Gift.

We are creating the Filter class based on the query string parameter and then call that class’s filter method to filter the result.

It is a bit complicated, but once you realize how the flow works then it is easy for you. For this example, you need to have a strong Object Oriented knowledge. Otherwise, it is hard to understand.

Laravel Filters example

 

So this is our API endpoint that, you can consume at the frontend.

Finally, our how to create filters in laravel tutorial is over. Thanks for taking.

1 Comment
  1. Robson Tenório says

    Very nice approach. But if you need a full query builder, just head to

    https://github.com/spatie/laravel-query-builder

Leave A Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.