Laravel Advanced Search Filters with Optional Fields

Hello Artisan, Sometimes we need to implement the filters with some optional fields like email, username, age etc. In this todays' topic, I'll try to cover how you can easily implement it in your Laravel application.

Note: Tested on Laravel 8.65.

Table of Contents

  1. Modify The Users Table
  2. Setup Model
  3. Create Dummy Records
  4. Create and Setup Controller
  5. Create Route
  6. Setup Blade Template
  7. Output

Modify The Users Table

At first, we need to modify our users table. Put the below code in our users_migration file.

database/migrations/2014_10_12_000000_create_users_table.php
<?php

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

class CreateUsersTable extends Migration
{
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->string('username')->unique();
            $table->string('age');
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('users');
    }
}

Now migrate using the below command.

php artisan migrate

Setup Model

Now open User.php file and replace the $fillable property with the blow code.

app/Models/User.php
protected $fillable = [
        'name',
        'email',
        'password',
        'username',
        'age'
    ];

Create Dummy Records

In this step, first we will modify our Default UserFactory.php. Replace the definition() function with the following code.

database/factories/UserFactory.php
public function definition()
    {
        return [
            'name' => $this->faker->name(),
            'email' => $this->faker->unique()->safeEmail(),
            'username' => $this->faker->unique()->userName,
            'age' => $this->faker->numberBetween(15,50),
            'email_verified_at' => now(),
            'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
            'remember_token' => Str::random(10),
        ];
    }

Now, we will use Tinker to create dummy records. If you don't familiar with Tinker, I recommend you to see one of my short tutorial using Tinker . Now, lets run the below command, which will create 500 user.

php artisan tinker
App\Models\User::factory()->count(500)->create()

Create and Setup Controller

At first we need to create a controller where we can put our logic. So, let's fire the below command in your terminal

php artisan make:controller UserController

This will create a file under app\Http\UserController.php, open the file paste the below code

app/Http/Controllers/UserController.php
<?php

namespace App\Http\Controllers;

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

class UserController extends Controller
{
    public function index()
    {
        $users = User::latest()->simplePaginate(20);

        return view('users',compact('users'));
    }

    public function filter(Request $request)
    {
        $users = User::query();

        $name = $request->name;
        $email = $request->email;
        $username = $request->username;
        $age = $request->age;

        if ($name) {
            $users->where('name','LIKE','%'.$name.'%');
        }
        if ($email) {
            $users->where('email','LIKE','%'.$email.'%');
        }

        if ($username) {
            $users->where('username','LIKE','%'.$username.'%');
        }

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

        $data = [
            'age' => $age,
            'email' => $email,
            'name' => $name,
            'username' => $username,
            'users' => $users->latest()->simplePaginate(20),
        ];

        return view('users',$data);
    }
}

Create Route

Now put the below route in your web.php

routes/web.php
Route::get('users',[\App\Http\Controllers\UserController::class,'index'])->name('users.index');
Route::get('users-filter',[\App\Http\Controllers\UserController::class,'filter'])->name('users.filter');

Setup Blade Template

In this step, first we need to create a blade file called users.blade.php and paste the below code

resources/views/users.blade.php
<html>
<head>
    <title></title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-12 mb-5">
            <div class="card">
                <div class="card-header">
                    <h2>Laravel 8 Advanced Search</h2>
                </div>
                <div class="card-body">
                    <form action="{{ route('users.filter') }}" method="GET">
                        <div class="row">
                            <div class="col-xl-3">
                                <label>Name</label>
                                <input type="text" name="name" class="form-control" value="{{ $name ?? '' }}">
                            </div>
                            <div class="col-xl-3">
                                <label>Email</label>
                                <input type="text" name="email" class="form-control" value="{{ $email ?? '' }}">
                            </div>
                            <div class="col-xl-3 mt-2">
                                <label>Username</label>
                                <input type="text" name="username" class="form-control" value="{{ $username ?? '' }}">
                            </div>
                            <div class="col-xl-3 mt-2">
                                <label>Age</label>
                                <input type="text" name="age" class="form-control" value="{{ $age ?? '' }}">
                            </div>
                            <div class="col-xl-12 text-right mt-2">
                                <button class="btn btn-primary" type="submit">Search</button>
                            </div>

                        </div>
                    </form>
                </div>
            </div>
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>#</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th>Username</th>
                    <th>Age</th>
                </tr>
                </thead>
                <tbody>
                @foreach ($users as $key => $user)
            <tr>
            <td> {{ $key+1 }}</td>
            <td> {{ $user->name }}</td>
            <td>{{ $user->email }}</td>
            <td>{{ $user->username }}</td>
            <td>{{ $user->age }}</td>
            </tr>

        @endforeach
                </tbody>
            </table>
            {{ $users->links() }}
        </div>
    </div>
</div>

</body>
</html>

Output

Now we are ready to run our project. Go to http://127.0.0.1:8000/users . and you'll find the below output.

User List

Now if you try to filter (by name, email, username or age) you will see it works. Look at the snippet of mine.

Search by Keyword "Name"

That's all for today. Hope you can enjoy this tutorial. You can download the project from GitHub also. Thanks for reading.