beratkara/searchable
Composer 安装命令:
composer require beratkara/searchable
包简介
Eloquent model search trait.
README 文档
README
This package is forked from "nicolaslopezj/searchable" package
Installation
Simply add the package to your composer.json file and run composer update.
"beratkara/searchable": "dev-master"
Usage
Add the trait to your model and your search rules.
use Nicolaslopezj\Searchable\SearchableTrait; class User extends \Eloquent { use SearchableTrait; /** * Searchable rules. * * @var array */ protected $searchable = [ /** * Columns and their priority in search results. * Columns with higher values are more important. * Columns with equal values have equal importance. * * @var array */ 'columns' => [ 'users.first_name' => 10, 'users.last_name' => 10, 'users.bio' => 2, 'users.email' => 5, 'posts.title' => 2, 'posts.body' => 1, ], 'joins' => [ 'posts' => ['users.id','posts.user_id'], ], ]; public function posts() { return $this->hasMany('Post'); } }
Now you can search your model.
// Simple search $users = User::search($query)->get(); // Search and get relations // It will not get the relations if you don't do this $users = User::search($query) ->with('posts') ->get();
Search Paginated
As easy as laravel default queries
// Search with relations and paginate $users = User::search($query) ->with('posts') ->paginate(20);
Mix queries
Search method is compatible with any eloquent method. You can do things like this:
// Search only active users $users = User::where('status', 'active') ->search($query) ->paginate(20);
Custom filters
// Restricted search $filters = [ [ 'type' => 'whereBetween', 'column' => 'created_at', 'data' => [ Carbon::now()->startOfDay()->format('Y-m-d H:i:s'), Carbon::now()->endOfDay()->format('Y-m-d H:i:s') ] ] ]; $users = User::where('status', 'active') ->searchRestricted($query, $filters) ->paginate(20);
Custom Threshold
The default threshold for accepted relevance is the sum of all attribute relevance divided by 4. To change this value you can pass in a second parameter to search() like so:
// Search with lower relevance threshold $users = User::where('status', 'active') ->search($query, 0) ->paginate(20);
The above, will return all users in order of relevance.
Entire Text search
By default, multi-word search terms are split and Searchable searches for each word individually. Relevance plays a role in prioritizing matches that matched on multiple words. If you want to prioritize matches that include the multi-word search (thus, without splitting into words) you can enable full text search by setting the third value to true. Example:
// Prioritize matches containing "John Doe" above matches containing only "John" or "Doe". $users = User::search("John Doe", null, true)->get();
If you explicitly want to search for full text matches only, you can disable multi-word splitting by setting the fourth parameter to true.
// Do not include matches that only matched "John" OR "Doe". $users = User::search("John Doe", null, true, true)->get();
How does it work?
Searchable builds a query that search through your model using Laravel's Eloquent. Here is an example query
Eloquent Model:
use Nicolaslopezj\Searchable\SearchableTrait; class User extends \Eloquent { use SearchableTrait; /** * Searchable rules. * * @var array */ protected $searchable = [ 'columns' => [ 'first_name' => 10, 'last_name' => 10, 'bio' => 2, 'email' => 5, ], ]; }
Search:
$search = User::search('Sed neque labore', null, true)->get();
Result:
select `users`.*, -- If third parameter is set as true, it will check if the column starts with the search -- if then it adds relevance * 30 -- this ensures that relevant results will be at top (case when first_name LIKE 'Sed neque labore%' then 300 else 0 end) + -- For each column you specify makes 3 "ifs" containing -- each word of the search input and adds relevace to -- the row -- The first checks if the column is equal to the word, -- if then it adds relevance * 15 (case when first_name LIKE 'Sed' || first_name LIKE 'neque' || first_name LIKE 'labore' then 150 else 0 end) + -- The second checks if the column starts with the word, -- if then it adds relevance * 5 (case when first_name LIKE 'Sed%' || first_name LIKE 'neque%' || first_name LIKE 'labore%' then 50 else 0 end) + -- The third checks if the column contains the word, -- if then it adds relevance * 1 (case when first_name LIKE '%Sed%' || first_name LIKE '%neque%' || first_name LIKE '%labore%' then 10 else 0 end) + -- Repeats with each column (case when last_name LIKE 'Sed' || last_name LIKE 'neque' || last_name LIKE 'labore' then 150 else 0 end) + (case when last_name LIKE 'Sed%' || last_name LIKE 'neque%' || last_name LIKE 'labore%' then 50 else 0 end) + (case when last_name LIKE '%Sed%' || last_name LIKE '%neque%' || last_name LIKE '%labore%' then 10 else 0 end) + (case when bio LIKE 'Sed' || bio LIKE 'neque' || bio LIKE 'labore' then 30 else 0 end) + (case when bio LIKE 'Sed%' || bio LIKE 'neque%' || bio LIKE 'labore%' then 10 else 0 end) + (case when bio LIKE '%Sed%' || bio LIKE '%neque%' || bio LIKE '%labore%' then 2 else 0 end) + (case when email LIKE 'Sed' || email LIKE 'neque' || email LIKE 'labore' then 75 else 0 end) + (case when email LIKE 'Sed%' || email LIKE 'neque%' || email LIKE 'labore%' then 25 else 0 end) + (case when email LIKE '%Sed%' || email LIKE '%neque%' || email LIKE '%labore%' then 5 else 0 end) as relevance from `users` group by `id` -- Selects only the rows that have more than -- the sum of all attributes relevances and divided by 4 -- Ej: (20 + 5 + 2) / 4 = 6.75 having relevance > 6.75 -- Orders the results by relevance order by `relevance` desc
统计信息
- 总下载量: 120
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 1
- 点击次数: 0
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2021-01-22