Search in Multiple Model using laravel-searchable

0
7290
search in multiple table

Spatie team recently released a new open source package called laravel-searchable . This package simplifies the search between multiple models. In this article, we will implement this package to search blog post and events records.

I hope you have already done database connection for your project. Now, we will create two tables posts and events that will store articles and events records. We will create model and migration for this using following command:

// for posts
php artisan make:model Post -m

// for events
php artisan make:model Event -m

This will create models and migrations for posts and events table. I will open the recently created migrations files and add the required fields. Thus, our posts migraiton file looks like below:

Schema::create('posts', function (Blueprint $table) {
    $table->increments('id');

    $table->string('title');
    $table->string('slug');
    $table->text('body');
    $table->string('submitted_by');
    $table->string('published_by');
    $table->string('status');
    $table->string('image')->nullable();
    $table->string('thumbnail')->nullable();

    $table->timestamps();
});

Similarly, our events migration file looks like below:

Schema::create('events', function (Blueprint $table) {
    $table->increments('id');

    $table->string('title');
    $table->string('slug');
    $table->datetime('date');
    $table->string('location');
    $table->text('description');
    $table->string('organizer')->nullable();
    $table->string('status');
    $table->string('image')->nullable();
    $table->string('thumbnail')->nullable();

    $table->timestamps();
});

So, To get started with the search function, let’s install the package first.

Install Package

We will install the package through composer. Run the following command:

composer require spatie/laravel-searchable

Create View

We need to create view file containing the input box for search function. We will also display the result in the same page. So, I have added extra code for displaying search results. Our final search blade looks like below:

@extends('frontend.layouts.default')

@section('page_title', 'laravel Search in Multiple Model')

@section('content')

@if ( $searchResults-> isEmpty())

Sorry, no results found for the term "{{ $searchterm }}".

@else

There are {{ $searchResults->count() }} results for the term "{{ $searchterm }}"


@foreach($searchResults->groupByType() as $type => $modelSearchResults)

{{ ucwords($type) }}

@foreach($modelSearchResults as $searchResult) @endforeach @endforeach @endif
@endsection

In this blade, I am extending a layout to give a nice overview. But, it’s not necessary to extend. You can either extends or simply display code between content section between basic HTML boilerplate.

Route Setup

To view this blade, we need to add routes in our web.php file. I will add four routes.

// display records routes
Route::get('events/{slug}', 'EventController@show')->name('events.show');
Route::get('posts/{slug}', 'NewsController@show')->name('posts.show');

// search routes
Route::get('laravel-search-in-multiple-model', 'SearchController@index')->name('search.index');
Route::get('search', 'SearchController@search')->name('search.result');

If you get the EventsController not found. error or NewsController not found. error(s), you can create new respective controller.

Modify Models

We already created our Post and Event models. We need to implements Searchable interface. Our Post model will be as follow:

id);

        return new SearchResult(
            $this,
            $this->title,
            $url
        );
    }
}

Similarly, our Event model looks like below:

id);

        return new SearchResult(
            $this,
            $this->title,
            $url
         );
    }

}

Be sure to import the interfaces at the top after namespace. We are using Spatie\Searchable\SearchResult interface which implements getSearchResult() method returning SearchResult object. Don’t worry, this is just a PHP 7 syntax. If you want to know more about this, you can read New Features In PHP 7 – Explained.

Within that SearchResult() object we need to specify three parameters: where are we searching (model itself – $this), what is the returned column for title (it will be displayed in results – so category name, $this->name), and what URL the result should link to (we’re building that with route() helper)

The SearchResult() method accepts 3 parameters i.e. the first one is model itself ($this), the second one column for a title that is returned and the last parameter is a route for displaying the specific record.

Controller

We will create a new controller that will process our search query. Simply run the below command to create one.

php artisan make:controller SearchController

Now, we will add two methods in this controller i.e. index and search. I have modify the controller file that looks like below:

input('query');

        $searchResults = (new Search())
                    ->registerModel(Post::class, 'title')
                    ->registerModel(Event::class, 'title')
                    ->perform($request->input('query'));

        return view('frontend.search', compact('searchResults', 'searchterm'));
    }

}

Now, it’s time to test the code. Before testing, I have seed the posts and events table. You can enter some random data for testing.

laravel search in multiple model_004
Events Table
laravel search in multiple model_005
Posts Table

After running php artisan serve, When we navigate to our route /laravel-search-in-multiple-model, we will get the view as below.
laravel search in multiple model

Similarly, when we write something on the input field and hit enter, we get the results as below:

When no record is found, we get no record found message.
laravel search in multiple model

This is all for searching records in multiple models using laravel-searchable. If you have any query or feedback, don’t forget to drop a comment below.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

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