How to search multiple models with Searchable in Laravel

In this shot, we will learn how to use Laravel Searchable to search for data on multiple models.

What is Laravel Searchable?

Laravel Searchable is a package used to get well-organized search results from different models of your application.

For example, a user can type the name of an author if they have forgotten the name of the book, and locating the author will help locate the book or vice versa. In this instance, you want your search bar to query both the user model and the author model. This is where Laravel Searchable becomes important.

Installation

Run the code below to install the package in your application:

composer require spatie/laravel-searchable

Model preparation

To allow Laravel Searchable to work on the model, we have to implement the Searchable interface on the models, like so:

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Spatie\Searchable\Searchable;
use Spatie\Searchable\SearchResult;

class Post extends Model implements Searchable
{
     public function getSearchResult(): SearchResult
     {
        $url = route('Post.show', $this->slug);
     
         return new \Spatie\Searchable\SearchResult(
            $this,
            $this->title,
            $url
         );
     }
}

Explanation

The code snippet above returns the URL and Title of the Post model. You can return whatever field you want from a particular model; these fields just relate to the post model.

After preparing the model, you can now use it from the controller:

$searchResults = (new Search())
   ->registerModel(User::class, 'name')
   ->registerModel(Post::class, 'title')
   ->search('john');

In the code above, we search for john in both the User model on the name attribute and the Post model on the title attribute. We loop through the result in our view, as shown below:

<h1>Search</h1>

There are {{ $searchResults->count() }} results.

@foreach($searchResults->groupByType() as $type => $modelSearchResults)
   <h2>{{ $type }}</h2>
   
   @foreach($modelSearchResults as $searchResult)
       <ul>
            <li><a href="{{ $searchResult->url }}">{{ $searchResult->title }}</a></li>
       </ul>
   @endforeach
@endforeach

Free Resources