Build search functionality with Laravel Scout and Vue.js

Rachid Laasri

Today, we are going to learn how to build a simple search functionality using Laravel Scout and Vue.js. If you don't know what Laravel Scout is, here is what the Laravel documentation says:

Laravel Scout provides a simple, driver based solution for adding full-text search to your Eloquent models. Using model observers, Scout will automatically keep your search indexes in sync with your Eloquent records.

It's an official package, not included in Laravel by default but you can still pull it in with Composer and use in your Laravel apps. It is shipped with Algolia driver, but you can swipe drivers easily as the documentation says:

Currently, Scout ships with an Algolia driver; however, writing custom drivers is simple and you are free to extend Scout with your own search implementations.

Before diving into the code, let's take a look at what we are going to be building:

Installing Laravel:

To install Laravel, open your terminal and cd into your folder and run this command:

composer create-project --prefer-dist laravel/laravel search

After executing the command, change your document root to point to the public folder and make sure directories within the storage and the bootstrap/cache directories are writable by your web server.

Last step in installing Laravel is generating an application key which is used to encrypt your user sessions and other data, and you can do that by running:

php artisan key:generate

If you open your website in the browser you should see this exact same page:

Database configuration:

Rename the .env.example file to .env and add your database name, user and password.

I will be using SQLite for this demo, feel free to use MySQL or any database management system you prefer.


If you don't specify a database name, Laravel assumes it is located in database/database.sqlite.

Models and migrations:

For this small app we will only be needing a Product model and a products table.

Go ahead and generate those two:

php artisan make:model Product -m

When passing the -m flag to the php artisan make:model command a migration will be generated for you. That's a cool trick to know!

These are the fields we are currently interested in:

class CreateProductsTable extends Migration
     * Run the migrations.
     * @return void
    public function up()
        Schema::create('products', function (Blueprint $table) {

     * Reverse the migrations.
     * @return void
    public function down()

Save your file and migrate your tables: php artisan migrate

Dummy data:

Using Laravel Model Factories we will be generating some fake data to test with. add these lines to database/factories/ModelFactory.php:

$factory->define(App\Product::class, function (Faker\Generator $faker) {
    return [
        'title' => $faker->sentence(),
        'image' => ''.rand(1, 100),
        'price' => $faker->numberBetween(3, 100),
        'description' => $faker->paragraph(2)

Our model factory is ready, let's create some data. In your command line run: php artisan tinker and then: factory(App\Product::class, 100)->create();. You can create as many records as you want, 100 sounds perfect to me.

Routes and Controllers:

These two routes are all what we need for this app, so let's go ahead and create them.

  • GET : / the home route, this route will render our website home page.


Route::get('/', function () {
    return view('home');

You can use a controller, but I really don't think it's necessary for this route.

  • GET : api/search this route is responsible for handling search requests.


Route::get('/search', [
    'as' => '',
    'uses' => 'Api\SearchController@search'

To create the SearchController class, simply run: php artisan make:controller Api\SearchController. If you didn't already know, when adding a namespace to your controller's class name Laravel will automatically create the folder for you and put the generated controller inside it.

class SearchController extends Controller
    public function search(Request $request)
        // we will be back to this soon!

Installing Laravel Scout:

Installing and configuring Laravel Scout is a breeze, you can pull the package using: composer require laravel/scout. When composer is done doing its thing add the ScoutServiceProvider to the providers array of your config/app.php configuration file:


Next, you should publish the Scout configuration using the vendor:publish Artisan command. This command will publish the scout.php configuration file to your config directory:

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

Finally, add the Laravel\Scout\Searchable trait to the Product to make it searchable:


namespace App;

use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model;

class Product extends Model
    use Searchable;

Importing data to Algolia

Now that Laravel Scout is installed and ready, it's time to install the Algolia driver

composer require algolia/algoliasearch-client-php

all we need to do now is to import the data we generated earlier to Algolia, You can create a free account ( No credit card is required ) if you want to follow up with this tutorial.

When you are done creating your account browse to and copy your Application ID and Admin API Key and put them in your .env file like this:


In your terminal run

php artisan scout:import "App\Product"

If you did everything correctly, you should see this message, which means that all your products table data got copied to Algolia's servers.

You can verify that by browsing to the Indices page in your account.

Writing the search method:

Back to the search method in app\Http\Controllers\Api\SearchController.php.

     * Search the products table.
     * @param  Request $request
     * @return mixed
    public function search(Request $request)
        // First we define the error message we are going to show if no keywords
        // existed or if no results found.
        $error = ['error' => 'No results found, please try with different keywords.'];

        // Making sure the user entered a keyword.
        if($request->has('q')) {

            // Using the Laravel Scout syntax to search the products table.
            $posts = Product::search($request->get('q'))->get();

            // If there are results return them, if none, return the error message.
            return $posts->count() ? $posts : $error;


        // Return the error message if no keywords existed
        return $error;

Don't forget to import the Product model use App\Product; Now, browsing to should return a JSON representation of your data.

The frontend setup:

We won't focus too much on the design in this tutorial, so here is the template we will be working with, copy/past it in your resources/home.blade.php file.

<!DOCTYPE html>
<html lang="en">
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <link rel="stylesheet" href="">
        <title>Search with Laravel Scout and Vue.js!</title>
        <div class="container">
            <div class="well well-sm">
                <div class="form-group">
                    <div class="input-group input-group-md">
                        <div class="icon-addon addon-md">
                            <input type="text" placeholder="What are you looking for?" class="form-control">
                        <span class="input-group-btn">
                            <button class="btn btn-default" type="button">Search!</button>
            <div id="products" class="row list-group">

You can see that all I have done is setup some boilerplate and import Twitter Bootstrap, you shouldn't be using the CDN for your real life apps, but since this is just a quick demo it's fine.

Importing Vue.js and vue-resource:

Add these lines before the body closing tag

Rachid Laasri

Yet another web developer.