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

jedrzej/searchable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation

    composer require jedrzej/searchable
    

    Add the trait to your Eloquent model:

    use Jedrzej\Searchable\SearchableTrait;
    
    class Post extends Model
    {
        use SearchableTrait;
    
        public $searchable = ['title', 'content', 'status'];
    }
    
  2. First Use Case Trigger a search via a request with query parameters:

    // Example request: /posts?search[title]=Laravel&search[status]=published
    $posts = Post::search()->get();
    

    The package automatically filters records based on the search[] parameters.

  3. Where to Look First

    • Model Definition: Check getSearchableAttributes() or $searchable property.
    • Request Handling: Ensure your controller routes requests to the model with search().
    • Documentation: Review the GitHub README for advanced configurations.

Implementation Patterns

Basic Workflow

  1. Define Searchable Fields

    class Product extends Model
    {
        use SearchableTrait;
    
        public $searchable = ['name', 'category_id', 'price'];
    }
    
    • Supports exact matches, partial matches, and range queries (e.g., price for numeric ranges).
  2. Trigger Searches

    • Single Field Search:
      $results = Product::search()->where('search[name]', 'like', '%Laptop%')->get();
      
    • Multi-Field Search (via request):
      // Request: /products?search[name]=Laptop&search[category_id]=5
      $results = Product::search()->get();
      
    • Dynamic Filtering (e.g., dropdowns):
      $results = Product::search()->where('search[category_id]', 5)->get();
      
  3. Integration with Controllers

    public function index(Request $request)
    {
        $query = Product::search();
        if ($request->has('search')) {
            $query->whereSearch($request->search);
        }
        return $query->paginate(10);
    }
    

Advanced Patterns

  1. Custom Search Logic Override scopeSearch() in your model for complex rules:

    public function scopeSearch($query)
    {
        if ($this->searchable && $search = request('search')) {
            foreach ($this->searchable as $field) {
                if (isset($search[$field])) {
                    $query->where($field, 'like', "%{$search[$field]}%");
                }
            }
        }
        return $query;
    }
    
  2. Combining with Other Traits Use with Sortable or Withable for full CRUD functionality:

    use Jedrzej\Sortable\SortableTrait;
    use Jedrzej\Withable\WithableTrait;
    
    class Post extends Model
    {
        use SearchableTrait, SortableTrait, WithableTrait;
    
        public $searchable = ['title', 'content'];
        public $sortable = ['created_at', 'title'];
        public $withable = ['author'];
    }
    
  3. API Resource Filtering

    public function index()
    {
        return ProductResource::collection(
            Product::search()->whereSearch(request('search'))->paginate()
        );
    }
    

Gotchas and Tips

Pitfalls

  1. Case Sensitivity

    • Default like queries are case-insensitive in MySQL but may vary by database. Use LOWER() for consistency:
      $query->whereRaw('LOWER(field) LIKE LOWER(?)', ["%{$value}%"]);
      
  2. Performance with Large Datasets

    • Avoid searching on non-indexed columns or text fields without FULLTEXT indexes.
    • Use select() to limit columns:
      Product::search()->select(['id', 'name', 'price'])->get();
      
  3. Request Parameter Naming

    • The package expects search[] parameters by default. Customize via:
      public function getSearchInputName()
      {
          return 'filter'; // Now uses `filter[]` instead of `search[]`
      }
      
  4. Boolean Fields

    • Directly pass 1/0 for boolean fields (e.g., ?search[is_active]=1).
  5. Reserved Words

    • Fields named or, and, or where may cause SQL errors. Rename or alias them:
      $query->where('is_active', 1)->getSearchResults();
      

Debugging Tips

  1. Log Queries Enable Laravel’s query logging to inspect generated SQL:

    DB::enableQueryLog();
    Product::search()->whereSearch(request('search'))->get();
    dd(DB::getQueryLog());
    
  2. Validate Input Sanitize search inputs to prevent SQL injection:

    $safeInput = strtolower(trim(request('search[name]'))); // Example
    
  3. Test Edge Cases

    • Empty searches (?search[]=).
    • Special characters (e.g., ' or ").
    • Numeric vs. string fields (e.g., id vs. price).

Extension Points

  1. Custom Operators Extend the trait to support custom operators (e.g., >=, <=):

    public function scopeWhereSearchGreaterThan($query, $field, $value)
    {
        return $query->where($field, '>=', $value);
    }
    
  2. Dynamic Field Whitelisting Use middleware to restrict searchable fields by user role:

    public function handle($request, Closure $next)
    {
        if (auth()->user()->isAdmin()) {
            $model->searchable = ['title', 'content', 'deleted_at'];
        } else {
            $model->searchable = ['title', 'published_at'];
        }
        return $next($request);
    }
    
  3. Localization Support multi-language searches by translating fields:

    public function getSearchableAttributes()
    {
        return ['title_' . app()->getLocale()];
    }
    
  4. Caching Results Cache frequent searches (e.g., autocomplete):

    $results = Cache::remember("search_{$query}", now()->addHours(1), function () {
        return Product::search()->whereSearch($query)->limit(10)->get();
    });
    
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui