loading...
Cover image for Create an easy fuzzy/loose search with Laravel 5

Create an easy fuzzy/loose search with Laravel 5

khalyomede profile image Khalyomede Updated on ・3 min read

What is what I call "fuzzy" or "loose" search ?

This is a great feature that let you retrieve results that partly match with your request terms.

1. Choose your champion

Shazam announce who he really is

First we need a model on which you want to perform the search.

For me, this will be my Schema.org Types. They are semantic objects that represent concepts, like : Shoe store, Product, Organizations, ...

2. Create an api route

Add a new route with a search method:

// routes/api.php

use Illuminate\Http\Request;

Route::get('type/search/{search?}', 'TypeController@search');

This route will be able to match routes like:

  • http://localhost:8000/api/type/search/acco
  • http://localhost:8000/api/type/search/accomodation
  • http://localhost:8000/api/type/search/store
  • http://localhost:8000/api/type/search/
  • ...

The interogation mark in {search?} means this parameter is not required. So you might encounter a valid API call like:

  • http://localhost:8000/api/type/search

3. Create a controller (if you did not yet)

If you do not have a TypeController yet, run this command to get up and running:

php artisan make:controller TypeController

You will find you controller on app/Http/Controllers/TypeController.php

4. Add the logic on your controller

// app/Http/Controllers/TypeController.php

namespace App\Http\Controllers;

use App\Type;
use Illuminate\Http\Request;;

class TypeController extends Controller {
  public function search(Request $request, $search = "") {
    if ($request->wantsJson()) {
      return response()->json(Type::search($search));
    } else {
      abort(403);
    }
  }
}

Here we are just saying:

If the request have been initiated using AJAX, return the result of the static method Type::search().

Else, it must have been the user browsing the route http://localhost:8000/api/type/search manually on his browser, so display a 403 page.

5. The search logic

I am something of a scientist myself meme

Write the search method on your Type model:

// app/Type.php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Type extends Model {
  protected $table = "type";
  protected $primaryKey = "id";

  public static function search(string $search) {
    $columns = ["id", "name", "partOf", "comment"];

    // If the search is empty, return everything
    if (empty(trim($search))) {
      return static::select($columns)->get();
    }
    // If the search contains something, we perform the fuzzy search 
    else {
      $fuzzySearch = implode("%", str_split($search)); // e.g. test -> t%e%s%t
      $fuzzySearch = "%$fuzzySearch%"; // test -> %t%e%s%t%s%

      return static::select($columns)->where("name", "like", $fuzzySearch)->get();
    }
  }
}

So the trick here is to use the LIKE SQL operator to do this.

6. Profit $$$

I am using the Insomnia client app to check that my fuzzy search is working.

Fuzzy type search showcase using Insomnia client app

Do not forget to add the header Accept: application/json to your request.

Hack it

One improvement would be to allow spaces in the search, so that routes like:

  • http://localhost:8000/api/type/search/acc+o
  • http://localhost:8000/api/type/search/shoe s tore

Will still return results.

Is this still possible meme

Just change this line in your Type model search method:

// app/Type.php

// $fuzzySearch = implode("%", str_split($search));
$fuzzySearch = implode("%", str_split(str_replace(" ", "", $search)));

Another hack you could make is to add several columns to the search using a ->orWhere("column2", "like", $fuzzySearch). You can find orWhere on the dedicated Laravel documentation.

In term of performance, if you are dealing with bunch of data, this will not fit your needs. That is why services like Algolia Search exist.

If you do not have the required budget, you could still be using the MATCH SQL operator (the keyword name might vary depending the database engine you choose). I found a pretty clean article explaining how to set this up using Laravel for the folks that are seeking a free faster alternative to this fuzzy search here if you do not fear some additional changes on your database schema.

Conclusion

I think this trick can let you offer your user some great search experience, to bring them more results items, requiring a few effort.

I would also be curious to see if my dear Laravelers have something else under the hat to bring fuzzy search to their users. Let me know in the comment.

Bye now, happy coding :)

Cat on a truck with a hat

Posted on Apr 20 '19 by:

khalyomede profile

Khalyomede

@khalyomede

Fullstack developer @ Carlili

Discussion

markdown guide