Easily add weighted searches through model attributes and relationships.
This package currently supports MySQL
and PostgreSQL
.
You can install the package via composer:
composer require maize-tech/laravel-searchable
You can publish the config file with:
php artisan vendor:publish --provider="Maize\Searchable\SearchableServiceProvider" --tag="searchable-config"
This is the content of the published config file:
return [
/*
|--------------------------------------------------------------------------
| Default match weight
|--------------------------------------------------------------------------
|
| The weight of all searched words which match at least one of the
| list of searchable attributes.
| Defaults to 1.
|
*/
'default_match_weight' => 1,
];
To use the package, add the Maize\Searchable\HasSearch
trait to each model you want to make searchable.
Once done, you can implement the getSearchableAttributes
abstract method by returning the list of attributes (or relationships' attributes) you want to search for.
You can also define the weight of each searchable attribute. If no weight is specified then default_match_weight
will be taken from config/searchable.php
.
Here's an example model including the HasSearch
trait:
<?php
namespace App\Models;
use Maize\Searchable\HasSearch;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Support\Facades\DB;
class Article extends Model
{
use HasSearch;
protected $fillable = [
'id',
'title',
'body',
'creator_name',
'creator_surname',
];
protected $casts = [
'body' => 'array',
];
/**
* Get the model's searchable attributes.
*
* @return array
*/
public function getSearchableAttributes(): array
{
return [
'title' => 5, // Model attribute
'body.en' => 2, // Single json key of a model attribute
'tags.name', // Relationship attribute
'tags.description.*', // All json keys of a relationship attribute
DB::raw("CONCAT(creator_name, ' ', creator_surname)"), // Raw expressions are supported too
];
}
/**
* Allows fetching the tags bound to current article instance
*
* @return BelongsToMany
*/
public function tags(): BelongsToMany
{
return $this->belongsToMany(Tag::class)->withTimestamps();
}
}
Now you can just search for a given term using the scopeSearch
scope method:
use App\Models\Article;
$searchTerm = 'the search string';
Article::query()
->search($searchTerm)
->where('column', '=', 'something')
->get();
That's all!
The package generates an SQL query with an 'or' condition for each search term and each searchable fields. The given query returns all models matching the search terms. Furthermore, search results are weighted, which means the query will be ordered by the most matching models.
If you don't want to order the search results by its match weight, you can set the orderByWeight
flag to false:
use App\Models\Article;
$searchTerm = 'the search string';
Article::query()
->search($searchTerm, false)
->where('column', '=', 'something')
->get();
composer test
Please see CHANGELOG for more information on what has changed recently.
Please see CONTRIBUTING for details.
Please review our security policy on how to report security vulnerabilities.
The MIT License (MIT). Please see License File for more information.