5 min read

Add Full Text Search With Algolia in Laravel

Are you tired of using a simple MySQL search in Laravel? Laravel provides a simple driver that you could add named Laravel Scout (in combination with Algolia or MeiliSearch), which adds full-text search to your Eloquent models.

Are you tired of using a simple MySQL search in Laravel? Laravel provides a easy-to-use driver that you could add named Laravel Scout (in combination with Algolia or MeiliSearch), which adds full-text search to your Eloquent models.

We’re going to implement Laravel Scout within a Laravel blog application that I have created on my YouTube Channel. The source code of the blog can be found right here, while the link of the tutorial can be found right here.

The Laravel complete blog has one important migration which is required for this tutorial, which is the /database/migrations/2021_02_22_174718_posts.php migration file. We are going to implement search on our posts, so we need to make sure that we migrate our migrations.

php artisan migrate

Pull in Laravel Scout & Algolia

Laravel offers a package named Laravel Scout that you can pull in through Composer.

composer require laravel/scout

This will pull in the necessary Laravel Scout packages. It will also create the /config/scout.php configuration file. The configuration file will be published depending on your Laravel version. In case your configuration file has not been published, Artisan offers you an option where you could publish it from the vendor directory.

php artisan vendor:publish –provider=”Laravel\Scout\ScoutServiceProvider”

Before we can interact with our search client, we need to make sure that we pull in Algolia through composer.

composer require algolia/algoliasearch-client-php

We can’t use Algolia out of the box. You need to make sure that you create an account on their official website. You can register and use their free trial which at the time of the creation of this blog article, lasts 14 days.

A quick tip that I could give you is to open the /config/scout.php file and search through the file for something that might stick out. As you might have noticed, it’s using a couple .env credentials which we actually haven’t setup. In my head, an alarm goes off which tells me that I somehow need to find API keys on Algolia’s site.

Navigate to the dashboard of Algolia, and click on the “API KEYS” menu item, where you need to copy the Application ID, which needs to be set equal to the ALGOLIA_APP_ID variable inside the .env file, and the Admin Api Key, which needs to be set equal to the ALGOLIA_SECRET_ID variable.

ALGOLIA_APP_ID="YOUR APP ID"
ALGOLIA_SECRET_ID="YOUR SECRET ID"

Marking your model for indexing

The next setup is marking the desired model for indexing. This can be done through the Searchable trait that we need to add inside the desired model. For this tutorial, we will be using the Post model.

Open the /app/Models/Post.php file and add the Searchable trait inside the Post class.

use Laravel\Scout\Searchable;

class Post extends Model
{
use HasFactory, Sluggable, Searchable;
}

The Searchable trait has tons of methods that you can use and there are too many to cover them inside the tutorial, if you are interested in the available methods, you can navigate to the /vendor/Laravel/scout/Searchable.php file.

It’s optional to override a method inside your model called searchableAs, which will define the model you want to search through. I usually override it to prevent mis confusion. Laravel will notice based on the model name which table needs to be used.

public function searchableAs()
{
    return 'posts';
}

Creating our Search Controller

We could add the search query inside the PostsController but I prefer to create a separate Controller which will handle the search. This way we’re keeping our code clean.

php artisan make:controller SearchController

Inside the /app/http/Controllers/SearchController.php file, we need to make sure that we create a new method which will do the check if the post exists, and returns the results back to the view.

public function query(Request $request)
{
    if($request->has('search')) {
        $posts = Post::search($request->search)->get();
    } else {
        $posts = Post::get();
    }

    return view('search.index', [
        'posts' => $posts
    ]);
}

We are returning a view right here which does not exist, make sure that you create a subdirectory called search with an index.blade.php file inside the /resources/views directory.

We need to make sure that we define the desires route(s) inside the browser so we could output results to the users. We can define the route(s) inside the /routes/web.php file:

use App\Http\Controllers \SearchController;

Route::get('/search/query', [SearchController::class, 'query'])->name('search.query');

Defining our frontend

The last step is to make sure that we add an input fields and submit button on our frontend where users can add a query string that they want to search through. Below our session check inside the /resources/views/blog/index.blade.php, let’s add:

<div class="pt-15 w-4/5 m-auto">
    <form action="{{ route('search.query) }}" method="GET">
        @csrf

        <input
            type="text"
            name="search"
            placeholder="Search..."
            class="pl-4 pr-10 py-3 leading-none rounded-lg shadow-sm focus:outline-none focus:shadow-outline text-gray-600 font-medium">

        <button
            type="submit"
            class="bg-green-500 uppercase bg-transparent text-gray-100 text-xs font-extrabold py-3 px-5 rounded-3xl">
            Submit
        </button>
    </form>
</div>

Obviously, the view we want to navigate users to does not exist yet, so we can copy paste the entire /resources/views/blog/index.blade.php file inside the /resources/views/search/index.blade.php file, and change the <h1> tag to:

<h1 class="text-6xl">
    Search blog posts...
</h1>

Inside the controller, we said that we want to return the same array that we receive inside the /resources/views/blog/index.blade.php, so there’s no need to make additional changes to our variables.

Import existing posts

The existing records in the database will not be imported into Algolia. Only records that we created after we started using Algolia will be imported. Laravel Scout offers a newly created command that imports old posts from our database into Algolia.

php artisan scout:import “App\Models\Post”

With one command, all existing posts have been imported into Algolia and they are all enabled for search!