5

What is the best way to implement the items filter functionality?

I have a table with some items, and each item has some fields.

How can I select items with fields filtering, like e-commerce filtering, using Laravel 5 and Eloquent?

trincot
  • 317,000
  • 35
  • 244
  • 286
aGoodRussianGuy
  • 173
  • 1
  • 1
  • 11

4 Answers4

8

I've always used eloquent scopes to filter eloquent results: https://laravel.com/docs/5.1/eloquent#query-scopes

Your Controller:

use App\Item;

class ItemController extends Controller
{
    public function index(Request $request)
    {
        $items = Item::name($request->name)->price($request->price)->paginate(25);

        return view('items.index', compact('items'));
    }
}

Your Model:

class Item extends Model
{
    public function scopeName($query, $name)
    {
        if (!is_null($name)) {
            return $query->where('name', 'like', '%'.$name.'%');
        }

        return $query;
    }

    public function scopePrice($query, $price)
    {
        if (!is_null($price)) {
            return $query->where(compact('price'));
        }

        return $query;
    }
}

Your View:

<form action="{{ route('items.index') }}" method="get">
    <input type="text" name="price" />
    <input type="text" name="name" />
    <input type="submit" value="Search">
</form>

@foreach($items as $item)
    {{ $item->name }}
@endforeach

{!! $items->render() !!}

In your scopes, you can check if the given value is null before limiting your query results. This effectively allows users to search and filter paginated results.

You could further enhance the search by automatic validation using Laravel's Form Requests so you can sure that the input they are searching for matches the data type for your query.

Keep in mind you'll have to modify the getRedirectUrl() method since your users will be executing a GET request and by default the getRedirectUrl() will contain the GET URL parameters resulting in an infinite loop since the one of the params failed validation.

Here's an example using the above:

class ItemSearchRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'name' => 'nullable|string|min:2|max:100',
            'price' => 'nullable|numeric',
        ];
    }

    protected function getRedirectUrl()
    {
        return url('/items');
    }
}
Steve Bauman
  • 8,165
  • 7
  • 40
  • 56
  • bro, its only show the result when input field of the price and name are the correct input with the database.,is that possible to filter like OR , input can be name only or price only,thats why ,can u give me a quick guide – Soul Coder Jun 27 '17 at 04:57
  • @SoulCoder The answer above is simply an example, you can use any kind of query logic you require for filtering. – Steve Bauman Dec 27 '18 at 16:05
5

I wrote a package for exactly this here: https://github.com/Tucker-Eric/EloquentFilter

It allows you to do something like:

use App\Item;

class ItemController extends Controller
{
    public function index(Request $request)
    {
        $items = Item::filter($request->all())->paginateFilter(25);

        return view('items.index', compact('items'));
    }
}
Eric Tucker
  • 6,144
  • 1
  • 22
  • 36
2

You can use this awesome laravel package: github.com/abdrzakoxa/laravel-eloquent-filter

<?php

namespace App\Http\Controllers;

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

class UserController extends Controller
{
    public function index(Request $request)
    {
        $users = Item::filter($request->all())->paginateFilter(10);

        return view('users.index', compact('users'));
    }
}
1

You can use package for regular index workflow to filter, sort, search and paginate https://packagist.org/packages/abyss403/request-meta

class UserController extends Controller
{
    ...
    public function index(Request $request){
        // Define model
        $model = new User();
        
        // Obtain collection based on request metadata
        $collection = \RequestMeta::load($model, $request)->data();
        
        // And just return it 
        return $collection;
       
        // OR using resources
        return new UserResourceCollection($collection);
    }
    ...
}

That's it

Andrey
  • 11
  • 2