masterro / laravel-searchable
通过 Eloquent 模型进行简单的全文搜索
v1.1.0
2020-12-09 16:42 UTC
Requires
- php: ^7.2|^8.0
- illuminate/database: ^6.0|^7.0|^8.0
- illuminate/pagination: ^6.0|^7.0|^8.0
- illuminate/support: ^6.0|^7.0|^8.0
Requires (Dev)
- nesbot/carbon: ^2.27
- orchestra/testbench: ^v5.0|^v6.0
README
Laravel 通过多个 Eloquent 模型进行简单的全文搜索
这是一个小型的 Laravel 扩展包,允许您通过多个 Eloquent 模型进行全局搜索,并按相关性排序结果集合。它使用 MATCH AGAINST MySQL 查询。
安装
步骤 1: Composer
在命令行中运行
composer require masterro/laravel-searchable
步骤 2: 服务提供者
如果您不使用 laravel 扩展包 自动发现,则需要注册服务提供者,打开 config/app.php
并在 providers
数组中追加
MasterRO\Searchable\SearchableServiceProvider::class
用法
在 AppServiceProvider 中注册您的搜索模型或创建您自己的一个
Searchable::registerModels([ Post::class, Article::class, User::class, ]);
然后您应该为每个注册的模型实现 MasterRO\Searchable\SearchableContract,或者它将被跳过并定义 searchable
方法
public static function searchable(): array { return ['title', 'description']; }
确保您已将全文索引添加到您的表中
public function up() { Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); $table->longText('description'); $table->dateTime('published_at')->nullable(); $table->timestamps(); }); DB::statement('ALTER TABLE posts ADD FULLTEXT search(title, description)'); }
现在您可以在控制器或您想要的任何地方进行搜索
public function search(Request $request, Searchable $searchable) { $query = trim($request->input('q')); if (mb_strlen($query) < 3) { return back()->withInput()->withErrors([ 'search_error' => __('messages.search_error') ]); } return view('search.index')->with('results', $searchable->search($query)); }
运行时搜索模型切换
$result = $this->searchable->searchModel(Post::class, 'consequatur');
$result = $this->searchable->searchModel([Article::class, Post::class], 'consequatur');
过滤
模型过滤
可以通过在您的模型中添加 filterSearchResults()
来过滤搜索结果(如 Eloquent 全局范围)
class User extends Model implements SearchableContract { public function posts() { return $this->hasMany(Post::class); } public function filterSearchResults($query) { return $query->whereHas('posts', function ($query) { $query->where('is_published', true); }); } }
上面的示例代码将过滤搜索结果,并且只返回发布过帖子的用户。
运行时过滤
可以通过添加自定义过滤回调来过滤搜索结果
$result = $this->searchable ->withFilter(function (Builder $query) { return $query->getModel() instanceof Post ? $query->where('description', '!=', 'Doloremque iure sequi quos sequi consequatur.') : $query; }) ->search('Dolorem');
禁用模型过滤
模型过滤器可以在运行时跳过,就像 Eloquent 全局范围一样。
$result = $this->searchable->withoutModelFilters()->search('quia est ipsa molestiae hic');
您可以指定跳过过滤器的模型
$result = $this->searchable ->withoutModelFilters(Post::class) ->search('quia est ipsa molestiae hic');
或
$result = $this->searchable ->withoutModelFilters([Article::class, Post::class]) ->search('quia est ipsa molestiae hic');
预加载(N+1 问题)
为了防止 N+1 问题,您可以预加载搜索结果的关系
$result = $this->searchable ->with([Article::class => 'author']) ->search('consequatur');
$result = $this->searchable ->with([ Article::class => [ 'author' => function ($query) { return $query->where('active', true); }, ], ]) ->searchModel(Article::class, 'consequatur');