Related content

Category : #laravel

Tags : #laravel, #laravel search

Laravel Scout provides a simple and very powerful, driver-based solution for adding full-text search in our Eloquent models. Using Laravel model observers, Scout automatically keeps our search indexes in sync with our Eloquent records. From Laravel 9 to Versions, Scout ships with Algolia, Meilisearch, and MySQL / PostgreSQL (database) drivers.

In this tutorial, I will show you a complete step by step guide on how to implement a full text search example with Laravel scout. I will use the User model to create this Laravel scout search example. So this Laravel 10 scout tutorial is going to be an amazing tutorial for you. We are going to follow some steps to complete this Laravel 10 scout search example.

I will use the database as scout driver. So let's see the example form of Laravel 10 scout search HTML form and this is going to be used to take input for searchable data:

laravel-10-scout-full-text-search

Step 1: Install Laravel

First of all, we need to get a fresh Laravel 10 version application using the bellow command, So open your terminal OR command prompt and run the bellow command to start laravel scout tutorial:

composer create-project laravel/laravel example-app

 

Step 2: Connect Database

After successfully installing the laravel app and then configuring the database setup. We will open the ".env" file and change the database name, username, and password in the env file to create how to create laravel scout tutorial.

.env

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=Enter_Your_Database_Name
DB_USERNAME=Enter_Your_Database_Username
DB_PASSWORD=Enter_Your_Database_Password

 

Read also: Laravel 10 Simple Eloquent Model Search Example

 

Step 3: Create Migration and Model

In this step, we need to create users table and model. then we need to run a migration. so let's change the files.

database/migrations/create_users_table.php

<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password');
            $table->rememberToken();
            $table->foreignId('current_team_id')->nullable();
            $table->string('profile_photo_path', 2048)->nullable();
            $table->timestamps();
        });
    }

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

 

Now update the user model by replacing it with the below code:

app/Models/User.php

<?php

namespace App\Models;

use Laravel\Scout\Searchable;
use Laravel\Sanctum\HasApiTokens;
use Laravel\Jetstream\HasProfilePhoto;
use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\TwoFactorAuthenticatable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasApiTokens;
    use HasFactory;
    use HasProfilePhoto;
    use Notifiable;
    use TwoFactorAuthenticatable;
    use Searchable;

    /**
     * The attributes that are mass assignable.
     *
     * @var string[]
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];
     
    public function toSearchableArray()
    {
        return [
            'name' => $this->name,
            'email' => $this->email,
        ];
    }
    
    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array
     */
    protected $hidden = [
        'password',
        'remember_token',
        'two_factor_recovery_codes',
        'two_factor_secret',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    /**
     * The accessors to append to the model's array form.
     *
     * @var array
     */
    protected $appends = [
        'profile_photo_url',
    ];
}

 

Now you have to run this migration by following the command:

php artisan migrate

 

Now update the seeder class like below:

Database\Seeders\DatabaseSeeder.php

<?php

namespace Database\Seeders;

use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Str;
use Illuminate\Database\Seeder;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;

class DatabaseSeeder extends Seeder
{
    public function run()
    {   
        for ($i=0; $i < 100; $i++) { 
            User::create([
                'name' => fake()->name(),
                'email' => fake()->unique()->safeEmail(),
                'email_verified_at' => now(),
                'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',
                'remember_token' => Str::random(10),
                'status' => $i % 2 === 0 ? 'active' : 'inactive'
            ]);
        }
    }
}

 

Now run the below command to insert some dummy data. Cause we need some demo data to search eloquent model using laravel scout.

php artisan db:seed

 

Step 4: Create Route

Here, we need to add one route to display the users data and make a search functionality in laravel 10 using scout. So add it like the below:

routes/web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TutorialController;

Route::get('/', [TutorialController::class,'index'])->name('index');

 

Step 5: Create Controller

Here, we need to add the index() method for fetching users data for create an advanced full text search in laravel using scout in TutorialController. so let's add like as below:

app/Http/Controllers/TutorialController.php

<?php

namespace App\Http\Controllers;

use App\Models\User;
use App\Jobs\ProcessCSVData;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Bus;
use Illuminate\Database\Eloquent\Builder;

class TutorialController extends Controller
{
    public function index(Request $request)
    {
        $users = User::search($request->q)->paginate(5);

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

 

Step 6: Install And Setup Scout

In this step, we will use scout to search for data from the model. Scout has a composer package and command. So install it by the below command:

composer require laravel/scout

 

Next, we may publish the configuration file like this:

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"

 

Now we have to set the database as a driver in your env file for laravel scout search example:

.env

SCOUT_DRIVER=database

 

Now run the below command to import data for searching:

php artisan scout:import "App\Models\User"

 

Now if you run this command, you will see the below output:

Imported [App\Models\User] models up to ID: 10
All [App\Models\User] records have been imported.

 

Step 7: Create Blade file

In this step, we need to create a welcome blade file and update the file. so let's change it.

resources/views/welcome.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">Laravel 10 Scout Full Text Search Example - Laravelia</div>
                 <div class="card-body">
                    <form action="{{ route('index') }}" method="get">
                        <div class="row">
                            <div class="col-md-10">
                                <input type="text" class="form-control mb-3" placeholder="search" name="q">
                            </div>
                            <div class="col-md-2">
                                <input type="submit" class="form-control mb-3" value="Search">
                            </div>
                        </div>
                    </form>
                    <table style="width: 100%">
                        <thead>
                            <th>#</th>
                            <th>Name</th>
                            <th>Email</th>
                            <th>Status</th>
                        </thead>
                        <tbody>
                            @foreach($users as $user)
                            <tr>
                                <td>{{ $loop->index + 1 }}</td>
                                <td>{{ $user->name }}</td>
                                <td>{{ $user->email }}</td>
                                <td>{{ $user->status == 'active' ? 'Active' : 'Inactive'}}</td>
                            </tr>
                            @endforeach
                        </tbody>
                    </table>
                    <center class="mt-5">
                        {{  $users->withQueryString()->links() }}
                    </center>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

 

Now create an app blade file and update it like this: 

resources/views/layouts/app.blade.php

<!doctype html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- CSRF Token -->
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <title>{{ config('app.name', 'Laravel') }}</title>
    
    <!-- Tailwindcss -->
    <script src="https://cdn.tailwindcss.com"></script>

    <!-- Scripts -->
    @vite(['resources/sass/app.scss', 'resources/js/app.js'])
    @stack('style')
</head>
<body>
    <div id="app">
        <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm">
            <div class="container">
                <a class="navbar-brand" href="{{ url('/') }}">
                    Laravelia
                </a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
                    <span class="navbar-toggler-icon"></span>
                </button>

                <div class="collapse navbar-collapse" id="navbarSupportedContent">
                    <!-- Left Side Of Navbar -->
                    <ul class="navbar-nav me-auto">

                    </ul>

                    <!-- Right Side Of Navbar -->
                    <ul class="navbar-nav ms-auto">
                        <!-- Authentication Links -->
                        @guest
                            @if (Route::has('login'))
                                <li class="nav-item">
                                    <a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
                                </li>
                            @endif

                            @if (Route::has('register'))
                                <li class="nav-item">
                                    <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
                                </li>
                            @endif
                        @else
                            <li class="nav-item dropdown">
                                <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
                                    {{ Auth::user()->name }}
                                </a>

                                <div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
                                    <a class="dropdown-item" href="{{ route('logout') }}"
                                       onclick="event.preventDefault();
                                                     document.getElementById('logout-form').submit();">
                                        {{ __('Logout') }}
                                    </a>

                                    <form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
                                        @csrf
                                    </form>
                                </div>
                            </li>
                        @endguest
                    </ul>
                </div>
            </div>
        </nav>

        <main class="py-4">
            @yield('content')
        </main>
    </div>
    @stack('script')
</body>
</html>

 

Ok, now we are ready to go and test the full text search in laravel. So let's run the project using this command:

php artisan serve

 

Now you can test our application by visiting the below URL:

URL
http://127.0.0.1:8000/

 

Conclusion

Now we know What is full-text search in laravel and what is laravel scout. Hope this laravel scout tutorial will help you to create full text search in laravel.