Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Fuzzy Search Laravel Package

ashiqfardus/laravel-fuzzy-search

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require ashiqfardus/laravel-fuzzy-search
    

    No publisher or config required—package auto-discovers.

  2. First Query:

    use AshiqFardus\LaravelFuzzySearch\Facades\FuzzySearch;
    
    $results = FuzzySearch::query('users')
        ->where('name', 'like', 'john')
        ->fuzzy('name', 'joh')
        ->get();
    

    Key: Use fuzzy() alongside Eloquent/Query Builder methods.

  3. First Use Case: Implement a search bar for a product catalog:

    $products = Product::query()
        ->fuzzy('name', request('q'))
        ->orFuzzy('description', request('q'))
        ->limit(10)
        ->get();
    

Where to Look First


Implementation Patterns

Core Workflows

  1. Eloquent Integration:

    // Basic fuzzy search
    $users = User::fuzzy('email', 'jane.doe@example')->get();
    
    // Combine with other clauses
    $activeUsers = User::where('active', true)
        ->fuzzy('name', 'john')
        ->orderBy('name')
        ->get();
    
  2. Query Builder Integration:

    $results = DB::table('products')
        ->fuzzy('title', 'wireless headphones')
        ->where('price', '<', 100)
        ->get();
    
  3. Multi-Field Search:

    $search = FuzzySearch::query('posts')
        ->fuzzy('title', 'laravel')
        ->orFuzzy('body', 'eloquent')
        ->get();
    
  4. Dynamic Search (API/Forms):

    // In a controller
    $query = User::query();
    if ($searchTerm = request('search')) {
        $query->fuzzy('name', $searchTerm)->orFuzzy('email', $searchTerm);
    }
    return $query->get();
    

Performance Patterns

  • Indexing: Use fuzzyIndex() for pre-computed columns (e.g., name_index):

    $users = User::fuzzyIndex('name_index', 'joh')->get();
    

    Tip: Add a fuzzy_index column via migration for static data.

  • Algorithm Selection:

    // Use 'levenshtein' for strict matches, 'soundex' for phonetic
    $results = User::fuzzy('name', 'john', 'soundex')->get();
    

    Default: 'levenshtein' (configurable in config/fuzzy-search.php).

  • Pagination:

    $results = User::fuzzy('name', 'joh')->paginate(10);
    

Advanced Patterns

  1. Custom Algorithms: Extend via service provider:

    // app/Providers/FuzzySearchServiceProvider.php
    public function register()
    {
        FuzzySearch::extend('custom', function ($query, $column, $term, $algorithm) {
            // Implement custom logic
        });
    }
    

    Use case: Domain-specific scoring (e.g., prioritize "Apple" over "apple").

  2. Full-Text + Fuzzy Hybrid:

    $results = Product::where('category', 'electronics')
        ->whereFulltext('name', 'wireless')
        ->fuzzy('brand', 'sony')
        ->get();
    
  3. Real-Time Search (Live Search):

    // Frontend (Vue/React)
    const debouncedSearch = _.debounce(async (term) => {
        const results = await axios.get(`/api/search?q=${term}`);
        // Update UI
    }, 300);
    

    Backend:

    Route::get('/api/search', function () {
        return User::fuzzy('name', request('q'))->limit(5)->get();
    });
    

Gotchas and Tips

Pitfalls

  1. Case Sensitivity:

    • Issue: Fuzzy search is case-sensitive by default.
    • Fix: Use ->fuzzy('column', 'term', 'levenshtein', true) (4th param for case-insensitive).
    • Alternative: Normalize data in migration:
      $table->string('name_lower')->nullable();
      
      Then search on name_lower.
  2. Performance with Large Datasets:

    • Issue: Full-table scans degrade performance.
    • Fix:
      • Add a fuzzy_index column (pre-computed hash).
      • Use ->limit() aggressively.
      • Cache frequent queries:
        $results = Cache::remember("fuzzy_search_{$term}", now()->addHours(1), function () use ($term) {
            return User::fuzzy('name', $term)->get();
        });
        
  3. Algorithm Mismatch:

    • Issue: 'soundex' fails for non-English names (e.g., "Müller").
    • Fix: Use 'levenshtein' or 'metaphone' for broader coverage.
  4. Reserved Keywords:

    • Issue: orFuzzy conflicts with Laravel’s orWhere.
    • Fix: Use ->orFuzzy() explicitly or alias:
      $query->macro('orFuzzy', function ($column, $term) {
          return $this->orWhere(function ($q) use ($column, $term) {
              $q->fuzzy($column, $term);
          });
      });
      

Debugging Tips

  1. Query Inspection: Enable SQL logging to verify generated queries:

    DB::enableQueryLog();
    $results = User::fuzzy('name', 'joh')->get();
    dd(DB::getQueryLog());
    
  2. Algorithm Validation: Test algorithms with edge cases:

    // Test 'soundex' with homophones
    $results = User::fuzzy('name', 'c', 'soundex')->get(); // Matches "C", "K", "Q"
    
  3. Index Utilization: Check if fuzzyIndex is used:

    // Should generate: `WHERE fuzzy_index LIKE '%hash%'`
    $results = User::fuzzyIndex('name_index', 'joh')->get();
    

Extension Points

  1. Custom Scoring: Override the default scoring logic in a service provider:

    FuzzySearch::macro('customScore', function ($query, $column, $term) {
        return $query->whereRaw("SOUNDEX($column) = SOUNDEX('$term')");
    });
    
  2. Database-Specific Optimizations:

    • MySQL: Use LIKE with wildcards for partial matches:
      $query->where($column, 'LIKE', "%{$term}%");
      
    • PostgreSQL: Leverage pg_trgm for faster fuzzy matches:
      $query->where("similarity($column, '$term') > 0.5");
      
  3. Search Analytics: Track search terms and results for UX improvements:

    event(new SearchPerformed(
        auth()->id(),
        request('q'),
        $results->count()
    ));
    

Configuration Quirks

  • Default Algorithm: Set in config/fuzzy-search.php:
    'default_algorithm' => 'metaphone', // or 'levenshtein', 'soundex'
    
  • Case Sensitivity: Toggle globally:
    'case_insensitive' => env('FUZZY_CASE_INSENSITIVE', false),
    
  • Reserved Columns: Exclude columns from fuzzy search (e.g., password):
    'ignored_columns' => ['password', 'remember_token'],
    

Pro Tips

  1. Combine with Laravel Scout: Use fuzzy search for backend fallbacks:

    if (request('q')) {
        $results = Product::search(request('q'))->get();
        if ($results->isEmpty()) {
            $results = Product::fuzzy('name', request('q'))->get();
        }
    }
    
  2. Typeahead Autocomplete: Limit results to top matches:

    $suggestions = User::fuzzy('name', 'jo')
        ->orderByRaw('LENGTH(name) - LENGTH(REPLACE(name, ?, ''))') // Prioritize shorter matches
        ->limit(5)
        ->pl
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle