Installation:
composer require nicolaslopezj/searchable:^1.0
Add the service provider in config/app.php (if not auto-discovered):
'providers' => [
Nicolaslopezj\Searchable\SearchableServiceProvider::class,
],
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,
],
];
First Search:
$results = User::search('john')->get();
// or with pagination
$results = User::search('john')->paginate(10);
$searchable array in your model.php artisan test if tests are included (though the package lacks tests).Basic Search:
// Simple search across configured columns
User::search('query')->get();
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'],
],
];
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;
}
Integration with API Resources: Use the search in API responses:
return User::search($request->query('q'))->paginate(15);
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();
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]);
}
Search in Multiple Models: Create a base model with the trait and reuse it:
class BaseModel extends Model
{
use SearchableTrait;
}
Search with Filters: Combine search with other query filters:
User::search('john')
->where('country', 'US')
->orderBy('created_at', 'desc')
->get();
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();
});
Performance:
LIKE queries, which can be slow for large datasets. Avoid searching on columns with low cardinality (e.g., status).php artisan schema:dump
Then manually add indexes in migrations:
$table->index('name');
$table->index('email');
Case Sensitivity:
LIKE queries are case-insensitive by default in MySQL but may vary in other databases.LOWER() for case-insensitive searches:
protected function performSearch($query, $search)
{
return $query->whereRaw("LOWER(name) LIKE LOWER(?)", ["%{$search}%"]);
}
Reserved Words:
table.column) may cause SQL errors.'columns' => [
'`users`.`first_name`' => 10, // MySQL
'"users"."first_name"' => 10, // PostgreSQL
],
Joins Without Relations:
$searchable['joins'] but the relation doesn’t exist, the search will fail silently.Priority Conflicts:
LIKE ordering.Deprecated Laravel Versions:
Log Raw Queries: Enable Laravel’s query logging to inspect generated SQL:
DB::enableQueryLog();
User::search('test')->get();
dd(DB::getQueryLog());
Check for Typos:
$searchable['columns'] against your database schema.Test with Simple Queries: Start with a single column to isolate issues:
protected $searchable = [
'columns' => ['users.name' => 10],
];
Custom Search Engine:
Replace the default LIKE logic by overriding performSearch() or extending the trait.
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
});
}
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');
});
Search Analytics: Use Laravel events to track searches:
User::search('query')->get();
// Listen for `searchable.searching` event
Multi-Tenant Search: Scope searches to the current tenant:
protected function performSearch($query, $search)
{
return $query->where('tenant_id', auth()->id())->where(...);
}
How can I help you explore Laravel packages today?