Blog Detail


A Laravel Package to Search Through Multiple Eloquent Models cover image

arrow_back A Laravel Package to Search Through Multiple Eloquent Models

There are many techniques to add search functionality to your Laravel project. You can use the Laravel Query Builder, use the Laravel Scout package to integrate with Algolia, or use different third-party packages. Today I’m introducing a new package called travel Cross Eloquent Search. This Laravel package allows you to search through multiple Eloquent models. It supports sorting, pagination, scoped queries, eager load relationships, and searching through single or multiple columns.


This package has a lot of awesome features that make it worthy to utilize in your projects.

  • Search through one or more Eloquent models.
  • Support for cross-model pagination.
  • Search through single or multiple columns.
  • Search through (nested) relationships.
  • Order by (cross-model) columns or by relevance.
  • Use constraints and scoped queries.
  • Eager load relationships for each model.
  • In-database sorting of the combined result.
  • Zero third-party dependencies


You can install this package via composer by running this command:

composer require protonemedia/laravel-cross-eloquent-search


Start your search query by adding one or more models to search through. Call the addmethod with the model’s class name and the column you want to search through. Then call the get method with the search term, and you’ll get a \Illuminate\Database\Eloquent\Collection instance with the results.

The results are sorted in ascending order by the updated column by default. In most cases, this column is updated_at. If you’ve customized your model’s UPDATED_AT constant, or overwritten the getUpdatedAtColumn method, this package will use the customized column. Of course, you can order by another column as well.

use ProtoneMedia\LaravelCrossEloquentSearch\Search;

$results = Search::add(Post::class, 'title')
    ->add(Video::class, 'title')

If you care about indentation, you can optionally use the new method on the facade:

    ->add(Post::class, 'title')
    ->add(Video::class, 'title')

You can add multiple models at once by using the addMany method:

    [Post::class, 'title'],
    [Video::class, 'title'],

There’s also an addWhen method, that adds the model when the first argument given to the method evaluates to true:

    ->addWhen($user, Post::class, 'title')
    ->addWhen($user->isAdmin(), Video::class, 'title')

Multi-word search

Multi-word search is supported out of the box. Simply wrap your phrase into double quotes.

Search::add(Post::class, 'title')
    ->add(Video::class, 'title')
    ->get('"macos big sur"');

You can disable the parsing of the search term by calling the dontParseTerm method, which gives you the same results as using double-quotes.

Search::add(Post::class, 'title')
    ->add(Video::class, 'title')
    ->get('macos big sur');


If you want to sort the results by another column, you can pass that column to the add method as a third parameter. Call the orderByDesc method to sort the results in descending order.

Search::add(Post::class, 'title', 'published_at')
    ->add(Video::class, 'title', 'released_at')

You can call the orderByRelevance method to sort the results by the number of occurrences of the search terms. Imagine these two sentences:

  • Apple introduces iPhone 13 and iPhone 13 mini
  • Apple unveils a new iPad mini with breakthrough performance in the stunning new design.

If you search for Apple iPad, the second sentence will come up first, as there are more matches of the search terms.

Search::add(Post::class, 'title')
    ->get('Apple iPad');

Ordering by relevance is not supported if you’re searching through (nested) relationships.

To sort the results by model type, you can use the orderByModel method by giving it your preferred order of the models:

    ->add(Comment::class, ['body'])
    ->add(Post::class, ['title'])
    ->add(Video::class, ['title', 'description'])
        Post::class, Video::class, Comment::class,
    ->get('Artisan School');


We highly recommend paginating your results. Call the paginate method before the get method, and you’ll get an instance of \Illuminate\Contracts\Pagination\LengthAwarePaginator as a result. The paginate method takes three (optional) parameters to customize the paginator. These arguments are the same as Laravel’s database paginator.

Search::add(Post::class, 'title')
    ->add(Video::class, 'title')

    // or
    ->paginate($perPage = 15, $pageName = 'page', $page = 1)


You may also use simple pagination. This will return an instance of \Illuminate\Contracts\Pagination\Paginator, which is not length aware:

Search::add(Post::class, ‘title’)
->add(Video::class, ‘title’)

// or
->simplePaginate($perPage = 15, $pageName = 'page', $page = 1)


Multiple columns per model

You can search through multiple columns by passing an array of columns as the second argument.

Search::add(Post::class, ['title', 'body'])
    ->add(Video::class, ['title', 'subtitle'])

In this blog, I’ve explained only some of the features & options of this package but there are a lot more options present in this package. If you are interested then you can visit their detailed documentation with code examples on Github.

Published at : 01-12-2021

Author : Rizwan Aslam
Rizwan Aslam

I am a highly results-driven professional with 12+ years of collective experience in the grounds of web application development especially in laravel, native android application development in java, and desktop application development in the dot net framework. Now managing a team of expert developers at Codebrisk.

Launch your project

Launch project