Skip to content

Latest commit

 

History

History
494 lines (371 loc) · 9.81 KB

File metadata and controls

494 lines (371 loc) · 9.81 KB

Getting Started with Laravel Fuzzy Search

This guide will help you get up and running with Laravel Fuzzy Search in just a few minutes.

Table of Contents

Installation

Requirements

  • PHP 8.0 or higher
  • Laravel 9.x, 10.x, 11.x, 12.x, or 13.x
  • MySQL, PostgreSQL, SQLite, or SQL Server

Install via Composer

composer require ashiqfardus/laravel-fuzzy-search

That's it! The package is auto-discovered and ready to use immediately.

Optional: Publish Configuration

php artisan vendor:publish --tag=fuzzy-search-config

This creates config/fuzzy-search.php where you can customize default settings.

Quick Start

1. Add the Searchable Trait

Add the Searchable trait to any Eloquent model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Ashiqfardus\LaravelFuzzySearch\Traits\Searchable;

class Article extends Model
{
    use Searchable;
}

2. Search Immediately (Zero Config)

The package auto-detects common column names:

// Automatically searches: title, name, email, description, etc.
$articles = Article::search('laravel')->get();

3. Customize Search Columns

For better results, specify which columns to search:

class Article extends Model
{
    use Searchable;

    protected array $searchable = [
        'columns' => [
            'title' => 10,        // Highest weight
            'body' => 5,          // Medium weight
            'excerpt' => 3,       // Lower weight
        ],
        'algorithm' => 'fuzzy',   // Default algorithm
        'typo_tolerance' => 2,    // Allow 2 character differences
    ];
}

Basic Usage

Simple Search

// Basic search
$results = Article::search('laravel')->get();

// With pagination
$results = Article::search('laravel')->paginate(20);

// Limit results
$results = Article::search('laravel')->take(10)->get();

Search with Filters

$results = Article::search('laravel')
    ->where('status', 'published')
    ->where('created_at', '>', now()->subDays(30))
    ->orderBy('created_at', 'desc')
    ->get();

Get Relevance Scores

$results = Article::search('laravel')
    ->withRelevance()
    ->get();

foreach ($results as $article) {
    echo "Score: " . $article->_score;
    echo "Title: " . $article->title;
}

Highlight Matches

$results = Article::search('laravel')
    ->highlight('mark')  // Wraps matches in <mark> tags
    ->get();

foreach ($results as $article) {
    echo $article->_highlighted['title'];
    // Output: "Getting started with <mark>Laravel</mark> Fuzzy Search"
}

Common Use Cases

1. Blog / Content Search

class Post extends Model
{
    use Searchable;

    protected array $searchable = [
        'columns' => [
            'title' => 10,
            'body' => 5,
            'excerpt' => 3,
        ],
    ];
}

// Usage
$posts = Post::search('getting started with laravel')
    ->where('status', 'published')
    ->paginate(15);

Or use the blog preset:

$posts = Post::search('getting started with laravel')
    ->preset('blog')
    ->paginate(15);

2. E-commerce Product Search

class Product extends Model
{
    use Searchable;

    protected array $searchable = [
        'columns' => [
            'name' => 10,
            'sku' => 8,
            'brand' => 6,
            'description' => 5,
        ],
        'typo_tolerance' => 1,  // Lower tolerance for SKUs
    ];
}

// Usage - handles typos automatically
$products = Product::search('iphone 15 pro')  // Finds "iPhone 15 Pro"
    ->where('stock', '>', 0)
    ->orderBy('price', 'asc')
    ->get();

Or use the ecommerce preset:

$products = Product::search('iphone 15 pro')
    ->preset('ecommerce')
    ->get();

3. User Search

class User extends Model
{
    use Searchable;

    protected array $searchable = [
        'columns' => [
            'name' => 10,
            'username' => 9,
            'email' => 8,
        ],
    ];
}

// Usage - finds users with typo tolerance
$users = User::search('john')  // Finds "John", "Jon", "Johnny"
    ->get();

Or use the users preset:

$users = User::search('john')
    ->preset('users')
    ->get();

4. Phonetic Search (Names)

Perfect for searching names that sound similar:

$users = User::search('steven')
    ->using('soundex')  // Finds "Stephen", "Stefan", "Stephan"
    ->get();

Or use the phonetic preset:

$users = User::search('steven')
    ->preset('phonetic')
    ->get();

5. Real-time Autocomplete

public function autocomplete(Request $request)
{
    $query = $request->input('q');
    
    $suggestions = Product::search($query)
        ->take(10)
        ->get(['name', 'sku', 'image']);
    
    return response()->json($suggestions);
}

With suggestions:

$suggestions = Product::search($query)
    ->suggest()  // Returns suggested completions
    ->take(10);

6. Multi-word Search

// Match ANY word (default)
$results = Article::search('laravel php framework')
    ->matchAny()  // Finds articles with "laravel" OR "php" OR "framework"
    ->get();

// Match ALL words
$results = Article::search('laravel php framework')
    ->matchAll()  // Only finds articles with all three words
    ->get();

7. Search Across Multiple Models

use Ashiqfardus\LaravelFuzzySearch\FederatedSearch;

$results = FederatedSearch::across([
    Article::class,
    Product::class,
    User::class,
])
    ->search('laravel')
    ->get();

foreach ($results as $result) {
    echo "Type: " . $result->_model_type;
    echo "Score: " . $result->_score;
}

Advanced Features

Custom Scoring

$results = Article::search('laravel')
    ->scoreWith(function($article, $baseScore) {
        // Boost recent articles
        $recencyBoost = $article->created_at->gt(now()->subDays(7)) ? 20 : 0;
        
        // Boost featured articles
        $featuredBoost = $article->is_featured ? 50 : 0;
        
        return $baseScore + $recencyBoost + $featuredBoost;
    })
    ->get();

Stop Words & Synonyms

$results = Article::search('the best laravel tutorial')
    ->ignoreStopWords(['the', 'a', 'an'])  // Ignores "the"
    ->withSynonyms([
        'tutorial' => ['guide', 'lesson', 'walkthrough']
    ])
    ->get();

Debugging

$results = Article::search('laravel')
    ->debugScore()  // Shows score breakdown
    ->get();

foreach ($results as $article) {
    print_r($article->_score_breakdown);
}

// Get debug info about search configuration
$debugInfo = Article::search('laravel')
    ->using('fuzzy')
    ->typoTolerance(2)
    ->getDebugInfo();

print_r($debugInfo);

Query Builder Support

You can also use fuzzy search directly on query builders:

use Illuminate\Support\Facades\DB;

// Simple where clause
$results = DB::table('articles')
    ->whereFuzzy('title', 'laravel')
    ->get();

// Multiple columns
$results = DB::table('articles')
    ->whereFuzzyMultiple(['title', 'body'], 'laravel')
    ->get();

Troubleshooting

No Results Returned

Problem: Search returns empty results even though data exists.

Solutions:

  1. Check if columns are searchable:
// Make sure columns are fillable or specified in $searchable
protected $fillable = ['title', 'body'];
  1. Lower typo tolerance temporarily:
$results = Article::search('test')
    ->typoTolerance(0)  // Exact matches only
    ->get();
  1. Use exact algorithm:
$results = Article::search('test')
    ->preset('exact')
    ->get();
  1. Enable debug mode:
$results = Article::search('test')
    ->debugScore()
    ->get();

Empty Search Term Error

Problem: EmptySearchTermException is thrown.

Solution: Either provide a search term or allow empty searches:

// Option 1: Check before searching
if (!empty($searchTerm)) {
    $results = Article::search($searchTerm)->get();
} else {
    $results = Article::all();
}

// Option 2: Enable in config
// config/fuzzy-search.php
'allow_empty_search' => true,

Slow Queries

Problem: Search queries are slow with large datasets.

Solutions:

  1. Enable search index:
// In config
'indexing' => [
    'enabled' => true,
    'async' => true,
],

// Build index
php artisan fuzzy-search:index Article
  1. Enable caching:
$results = Article::search('laravel')
    ->cache(60)  // Cache for 60 minutes
    ->get();
  1. Reduce columns searched:
// Only search most important columns
$results = Article::search('laravel')
    ->searchIn(['title' => 10])  // Only search title
    ->get();
  1. Use simple algorithm for large datasets:
$results = Article::search('laravel')
    ->using('simple')  // Faster but less typo-tolerant
    ->get();

Invalid Algorithm Error

Problem: InvalidAlgorithmException is thrown.

Solution: Use a valid algorithm:

// Valid algorithms: fuzzy, levenshtein, soundex, trigram, simple
$results = Article::search('test')
    ->using('fuzzy')  // ✓ Valid
    ->get();

Next Steps

Need Help?