masterro/searchable

此包已被弃用且不再维护。作者建议使用masterro/laravel-searchable包。

通过Eloquent模型进行简单的全文搜索

v1.1.0 2020-12-09 16:42 UTC

This package is auto-updated.

Last update: 2022-04-01 13:57:53 UTC


README

Latest Stable Version Total Downloads Build Status Build status License

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');