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

Searchable Laravel Package

ahmedabdo/searchable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require ahmedabdo/searchable
    

    Publish the config (if needed):

    php artisan vendor:publish --provider="Abdo\Searchable\SearchableServiceProvider"
    
  2. First Use Case Add the Searchable trait and define searchable columns in your model:

    use Abdo\Searchable\Searchable;
    use Abdo\Searchable\Attributes\SearchColumns;
    
    class User extends Authenticatable
    {
        use Searchable;
    
        #[SearchColumns]
        public $searchable = [
            "columns" => ["name", "email"],
        ];
    }
    

    Search via a query scope:

    $results = User::search('john')->get();
    
  3. Where to Look First

    • Model Setup: Focus on the searchable array in your model.
    • Query Scopes: Use search() and filter() methods in queries.
    • Blade Helpers: Check filter-blade-script for UI integration.

Implementation Patterns

Core Workflows

  1. Basic Search

    // Search across defined columns
    User::search('john doe')->get();
    
  2. Filtering

    // Filter by exact match (default)
    User::filter('role.name', 'admin')->get();
    
    // Use operators (e.g., `contains`, `starts_with`)
    User::filter('email', 'contains', 'test@example')->get();
    
  3. Combining Search and Filter

    User::search('john')
        ->filter('role.name', 'admin')
        ->get();
    
  4. Dynamic Column Configuration Override searchable columns per query:

    User::search('query', ['columns' => ['name', 'email', 'phone']])->get();
    
  5. Custom Search Logic Use customSearch() for complex queries:

    User::customSearch(function ($query, $search) {
        return $query->where('name', 'like', "%{$search}%")
                     ->orWhere('email', 'like', "%{$search}%");
    })->get();
    

Integration Tips

  • APIs: Return filtered/search results as JSON:
    return User::search(request('q'))->filter(request('filters'))->get();
    
  • Blade: Use the provided Blade directive for filter forms:
    @filterForm(['role.name', 'email'])
    
  • Testing: Mock the trait or use partialMock for model tests:
    $mock = $this->partialMock(User::class, ['searchable']);
    

Gotchas and Tips

Pitfalls

  1. Eager Loading

    • Forgetting to define eager relationships in searchable causes N+1 queries:
      #[SearchColumns]
      public $searchable = [
          "columns" => ["role.name"], // Requires eager loading
          "eager" => ["role"]         // <-- Critical!
      ];
      
  2. Case Sensitivity

    • Default searches are case-insensitive. For case-sensitive searches, override the trait’s search() method.
  3. Reserved Keywords

    • Avoid column names like created_at without escaping (use backticks in raw queries if needed).
  4. Performance

    • Full-text search on large tables may require database-level optimizations (e.g., FULLTEXT indexes).

Debugging

  • Query Logs: Enable Laravel’s query logging to inspect generated SQL:
    DB::enableQueryLog();
    User::search('test')->toSql(); // Dump raw SQL
    
  • Filter Validation: Use filter() with invalid operators silently fails. Validate inputs:
    $validOperators = ['contains', 'starts_with', 'exact'];
    if (!in_array(request('operator'), $validOperators)) {
        abort(400, 'Invalid operator');
    }
    

Extension Points

  1. Custom Operators Extend the FilterOperator class or add via config:

    // config/searchable.php
    'operators' => [
        'custom_operator' => function ($column, $value) {
            return "UPPER({$column}) LIKE UPPER('%{$value}%')";
        },
    ];
    
  2. Global Searchable Config Override defaults in config/searchable.php:

    'default_columns' => ['name', 'email'], // Fallback columns
    'default_eager' => [],                  // Global eager loads
    
  3. Macros for Query Builder Add reusable search/filter macros:

    \Illuminate\Database\Eloquent\Builder::macro('scopeAdvancedSearch', function ($query, $search) {
        return $query->where(function ($q) use ($search) {
            $q->where('name', 'like', "%{$search}%")
              ->orWhere('email', 'like', "%{$search}%");
        });
    });
    

Pro Tips

  • Partial Matches: Use contains or starts_with for flexible searches:
    User::filter('name', 'contains', 'doe')->get(); // Matches "John Doe"
    
  • Pagination: Combine with Laravel’s pagination:
    User::search('query')->paginate(10);
    
  • Caching: Cache frequent searches (e.g., autocomplete):
    Cache::remember("search_{$query}", now()->addHours(1), function () use ($query) {
        return User::search($query)->pluck('name')->toArray();
    });
    
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity