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

nicolaslopezj/searchable

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require nicolaslopezj/searchable:^1.0
    

    Add the service provider in config/app.php (if not auto-discovered):

    'providers' => [
        Nicolaslopezj\Searchable\SearchableServiceProvider::class,
    ],
    
  2. Basic Setup: Use the SearchableTrait in your Eloquent model and define $searchable rules:

    use Nicolaslopezj\Searchable\SearchableTrait;
    
    class User extends Model
    {
        use SearchableTrait;
    
        protected $searchable = [
            'columns' => [
                'users.name' => 10,
                'users.email' => 5,
            ],
        ];
    
  3. First Search:

    $results = User::search('john')->get();
    // or with pagination
    $results = User::search('john')->paginate(10);
    

Where to Look First

  • Model Configuration: Focus on the $searchable array in your model.
  • Documentation: The README covers basic usage, but the source code is minimal and self-explanatory.
  • Testing: Run php artisan test if tests are included (though the package lacks tests).

Implementation Patterns

Core Workflows

  1. Basic Search:

    // Simple search across configured columns
    User::search('query')->get();
    
  2. Search with Relations: Define joins in $searchable['joins'] and reference related columns:

    protected $searchable = [
        'columns' => [
            'posts.title' => 5, // Search in posts.title
        ],
        'joins' => [
            'posts' => ['users.id', 'posts.user_id'],
        ],
    ];
    
  3. Dynamic Search Rules: Override getSearchableRules() to conditionally modify rules:

    public function getSearchableRules()
    {
        $rules = $this->searchable;
        if ($this->isAdmin()) {
            $rules['columns']['users.email'] = 20; // Higher priority for admins
        }
        return $rules;
    }
    
  4. Integration with API Resources: Use the search in API responses:

    return User::search($request->query('q'))->paginate(15);
    
  5. Combining with Scopes: Add a scope to extend search functionality:

    public function scopeActive($query)
    {
        return $query->where('active', 1);
    }
    // Usage:
    User::active()->search('query')->get();
    

Advanced Patterns

  1. Custom Search Logic: Extend the trait or override performSearch():

    protected function performSearch($query, $search)
    {
        // Custom logic (e.g., full-text search)
        return $query->whereRaw("MATCH(name, email) AGAINST(? IN BOOLEAN MODE)", [$search]);
    }
    
  2. Search in Multiple Models: Create a base model with the trait and reuse it:

    class BaseModel extends Model
    {
        use SearchableTrait;
    }
    
  3. Search with Filters: Combine search with other query filters:

    User::search('john')
        ->where('country', 'US')
        ->orderBy('created_at', 'desc')
        ->get();
    
  4. Caching Search Results: Cache frequent searches (e.g., autocomplete):

    $cacheKey = "search_users_{$query}";
    $results = Cache::remember($cacheKey, now()->addMinutes(5), function () use ($query) {
        return User::search($query)->get();
    });
    

Gotchas and Tips

Pitfalls

  1. Performance:

    • The package uses LIKE queries, which can be slow for large datasets. Avoid searching on columns with low cardinality (e.g., status).
    • Tip: Add database indexes to frequently searched columns:
      php artisan schema:dump
      
      Then manually add indexes in migrations:
      $table->index('name');
      $table->index('email');
      
  2. Case Sensitivity:

    • LIKE queries are case-insensitive by default in MySQL but may vary in other databases.
    • Tip: Use LOWER() for case-insensitive searches:
      protected function performSearch($query, $search)
      {
          return $query->whereRaw("LOWER(name) LIKE LOWER(?)", ["%{$search}%"]);
      }
      
  3. Reserved Words:

    • Column names with spaces or special characters (e.g., table.column) may cause SQL errors.
    • Tip: Use backticks or quotes:
      'columns' => [
          '`users`.`first_name`' => 10, // MySQL
          '"users"."first_name"' => 10, // PostgreSQL
      ],
      
  4. Joins Without Relations:

    • If you define a join in $searchable['joins'] but the relation doesn’t exist, the search will fail silently.
    • Tip: Ensure all joins have corresponding model methods.
  5. Priority Conflicts:

    • Equal priorities may not behave as expected due to SQL LIKE ordering.
    • Tip: Use distinct priority values (e.g., 10, 9, 8) for critical columns.
  6. Deprecated Laravel Versions:

    • The package supports Laravel 4.2+ and 5.0, but some features may not work in older versions.
    • Tip: Test thoroughly if using Laravel < 5.5.

Debugging Tips

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

    DB::enableQueryLog();
    User::search('test')->get();
    dd(DB::getQueryLog());
    
  2. Check for Typos:

    • Validate column names in $searchable['columns'] against your database schema.
  3. Test with Simple Queries: Start with a single column to isolate issues:

    protected $searchable = [
        'columns' => ['users.name' => 10],
    ];
    

Extension Points

  1. Custom Search Engine: Replace the default LIKE logic by overriding performSearch() or extending the trait.

  2. Add Search Metrics: Track search performance or popularity:

    protected static function bootSearchableTrait()
    {
        static::addGlobalScope('logSearch', function (Builder $builder) {
            $builder->getQuery()->from = 'search_logs';
            // Custom logic to log searches
        });
    }
    
  3. Search Highlighting: Integrate with a library like laravel-html-string to highlight matches:

    $results = User::search('john')->get();
    $highlighted = $results->map(function ($user) {
        return Highlighter::highlight($user->name, 'john');
    });
    
  4. Search Analytics: Use Laravel events to track searches:

    User::search('query')->get();
    // Listen for `searchable.searching` event
    
  5. Multi-Tenant Search: Scope searches to the current tenant:

    protected function performSearch($query, $search)
    {
        return $query->where('tenant_id', auth()->id())->where(...);
    }
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
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
christhompsontldr/laravel-inky
spatie/mailcoach-vapor