10分钟掌握 Laravel 模型搜索神器:Searchable 完全指南

10分钟掌握 Laravel 模型搜索神器:Searchable 完全指南

【免费下载链接】searchable A php trait to search laravel models 【免费下载链接】searchable 项目地址: https://gitcode.com/gh_mirrors/se/searchable

你是否还在为 Laravel 项目中的搜索功能编写复杂 SQL?是否因全文搜索插件配置繁琐而头疼?本文将带你从零掌握 Searchable trait 的全部用法,通过 7 个实战场景、12 段可直接复用的代码和 3 个优化技巧,让你的模型搜索效率提升 300%。读完本文你将获得:

  • 5 分钟快速集成的搜索实现方案
  • 多字段权重排序与关联表查询技巧
  • MySQL/PostgreSQL 跨数据库适配方案
  • 性能优化的 3 个核心配置参数

项目概述

Searchable(搜索 trait)是一个轻量级 Laravel Eloquent 扩展,通过 trait 注入方式为模型添加智能搜索能力。它允许开发者为不同字段设置搜索优先级,支持关联表查询,并能基于匹配度自动计算相关性分数。与 Laravel Scout 相比,Searchable 无需额外服务依赖,原生支持数据库索引,更适合中小规模项目的快速集成。

// 核心特性一览
$searchable = [
  'columns' => [           // 字段权重配置
    'users.name' => 10,    // 高优先级字段
    'users.email' => 5,    // 中优先级字段
    'posts.content' => 3   // 低优先级关联字段
  ],
  'joins' => [             // 关联表配置
    'posts' => ['users.id', 'posts.user_id']
  ],
  'groupBy' => 'users.id'  // 去重配置
];

安装与环境配置

系统要求

环境依赖最低版本推荐版本
PHP5.4.08.2+
Laravel4.211.x
数据库MySQL 5.5/PostgreSQL 9.4MySQL 8.0/PostgreSQL 14
扩展mbstringmbstring (启用 Unicode 支持)

快速安装

通过 Composer 集成到 Laravel 项目:

composer require nicolaslopezj/searchable:1.*

国内用户可配置阿里云 Composer 镜像加速:

composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/

基础使用指南

1. 模型配置

在需要搜索功能的 Eloquent 模型中引入 trait 并定义搜索规则:

// app/Models/User.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Nicolaslopezj\Searchable\SearchableTrait;

class User extends Model
{
    use SearchableTrait;

    /**
     * 搜索配置
     * @var array
     */
    protected $searchable = [
        'columns' => [
            'users.name' => 10,          // 姓名权重最高
            'users.email' => 5,          // 邮箱次之
            'users.bio' => 3,            // 个人简介权重较低
            'posts.title' => 8,          // 关联文章标题
            'posts.content' => 2         // 关联文章内容
        ],
        'joins' => [                     // 定义关联关系
            'posts' => ['users.id', 'posts.user_id']
        ]
    ];

    // 关联定义(必须)
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

2. 基本搜索操作

// 简单搜索
$users = User::search('john')->get();

// 带分页的搜索结果
$users = User::search('john')
             ->paginate(20);

// 搜索并加载关联数据
$users = User::search('john')
             ->with('posts')
             ->get();

// 条件筛选 + 搜索
$activeUsers = User::where('status', 'active')
                   ->search('john')
                   ->orderBy('relevance', 'desc')
                   ->get();

高级功能详解

权重配置策略

Searchable 通过字段权重控制搜索结果排序,建议遵循以下配置原则:

mermaid

最佳实践示例

protected $searchable = [
    'columns' => [
        // 用户搜索场景
        'name' => 15,       // 姓名(高辨识度)
        'username' => 12,   // 用户名(唯一标识)
        'email' => 10,      // 邮箱(高唯一度)
        'mobile' => 10,     // 手机号(高唯一度)
        'company' => 8,     // 公司(中等辨识度)
        'bio' => 3          // 个人简介(低辨识度)
    ]
];

多模式搜索控制

Searchable 提供四种搜索模式,满足不同场景需求:

模式方法适用场景性能影响
标准搜索search($query)常规场景
精确匹配优先search($query, null, true)关键词高亮场景
完全匹配search($query, null, true, true)精确查找场景
限制搜索searchRestricted($query, $closure)权限过滤场景

精确匹配示例

// 优先完全匹配"John Doe",再匹配包含"John"或"Doe"的结果
$users = User::search("John Doe", null, true)->get();

// 仅返回完全匹配"John Doe"的结果
$users = User::search("John Doe", null, true, true)->get();

关联表搜索

支持跨表联合搜索,自动处理表连接逻辑:

// 多表关联配置示例
protected $searchable = [
    'columns' => [
        'users.name' => 10,
        'posts.title' => 8,
        'comments.content' => 5,
        'tags.name' => 7
    ],
    'joins' => [
        'posts' => ['users.id', 'posts.user_id'],
        'comments' => ['posts.id', 'comments.post_id'],
        'taggables' => ['posts.id', 'taggables.taggable_id', 'taggable_type', 'App\Models\Post'],
        'tags' => ['taggables.tag_id', 'tags.id']
    ]
];

⚠️ 注意:多表关联会增加查询复杂度,建议控制关联表数量不超过 3 个,并确保关联字段已建立索引。

自定义相关性阈值

默认阈值为所有字段权重总和的平均值,可根据需求调整:

// 获取权重总和
$totalWeight = array_sum($this->searchable['columns']);

// 降低阈值(返回更多结果)
$users = User::search($query, $totalWeight * 0.3)->get();

// 提高阈值(返回更精准结果)
$users = User::search($query, $totalWeight * 0.7)->get();

// 完全禁用阈值过滤(返回所有匹配项)
$users = User::search($query, 0)->get();

实现原理深度解析

Searchable 的核心原理是构建包含权重计算的 SQL 查询,以下是其执行流程:

mermaid

生成的 SQL 示例(MySQL):

SELECT 
  `users`.*,
  -- 权重计算逻辑
  (case when LOWER(`name`) LIKE 'john%' then 150 else 0 end) +
  (case when LOWER(`email`) LIKE 'john%' then 100 else 0 end) +
  (case when LOWER(`name`) LIKE '%john%' then 15 else 0 end) +
  (case when LOWER(`email`) LIKE '%john%' then 10 else 0 end) 
  as relevance 
FROM `users` 
GROUP BY `id` 
HAVING relevance > 61.25 
ORDER BY `relevance` desc

性能优化指南

索引优化

为搜索字段添加合适的索引可提升查询速度 5-10 倍:

-- 单列索引(推荐)
CREATE INDEX idx_users_name ON users(name);
CREATE INDEX idx_users_email ON users(email);

-- 复合索引(多字段搜索场景)
CREATE INDEX idx_users_name_email ON users(name, email);

-- 关联字段索引(必须)
CREATE INDEX idx_posts_user_id ON posts(user_id);

查询优化

  1. 限制返回字段
// 仅返回必要字段
$users = User::search($query)
             ->select('id', 'name', 'email', 'relevance')
             ->get();
  1. 分页控制
// 合理设置分页大小(建议20-50条/页)
$users = User::search($query)->paginate(30);
  1. 避免N+1查询
// 预加载关联数据
$users = User::search($query)
             ->with('posts:id,title,user_id') // 仅加载必要字段
             ->get();

高级配置

通过调整以下参数优化搜索性能:

// 1. 自定义相关性字段名(避免冲突)
protected $relevanceField = 'search_relevance';

// 2. 配置分组(解决重复结果)
protected $searchable = [
    'groupBy' => 'users.id', // 按主表ID分组
    // ...
];

// 3. 数据库特定优化(PostgreSQL示例)
protected function isPostgresqlDatabase()
{
    return $this->getDatabaseDriver() == 'pgsql';
}

常见问题解决方案

中文搜索支持

默认配置下中文搜索可能效果不佳,可通过以下方案解决:

// 1. 修改分词逻辑(app/Models/Traits/CustomSearchable.php)
trait CustomSearchable
{
    protected function getSearchQueriesForColumn($column, $relevance, array $words)
    {
        // 中文分词处理(需安装scws扩展或使用其他分词库)
        $words = $this->splitChineseWords(implode(' ', $words));
        return parent::getSearchQueriesForColumn($column, $relevance, $words);
    }
    
    protected function splitChineseWords($text)
    {
        // 实现中文分词逻辑
        return preg_split('/(?<!^)(?!$)/u', $text); // 简单按字符拆分示例
    }
}

大数据量搜索优化

当数据量超过10万条时,建议:

  1. 使用数据库视图:预定义关联查询视图
  2. 添加缓存层:缓存热门搜索结果
  3. 考虑专业搜索引擎:Elasticsearch + Laravel Scout

版本兼容性处理

不同 Laravel 版本的适配方案:

// Laravel 8+ 模型命名空间适配
use Illuminate\Database\Eloquent\Model;

// Laravel 5.4-7 兼容处理
if (!method_exists(Model::class, 'search')) {
    trait SearchableTraitCompatibility
    {
        // 兼容代码
    }
}

完整示例:用户搜索功能实现

1. 模型完整配置

// app/Models/User.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Nicolaslopezj\Searchable\SearchableTrait;

class User extends Model
{
    use SearchableTrait;

    protected $fillable = [
        'name', 'email', 'username', 'bio', 'company'
    ];

    protected $searchable = [
        'columns' => [
            'name' => 15,
            'username' => 12,
            'email' => 10,
            'company' => 8,
            'bio' => 3
        ],
        'groupBy' => 'id'
    ];

    // 自定义相关性字段名
    protected $relevanceField = 'user_relevance';
}

2. 控制器实现

// app/Http/Controllers/SearchController.php
namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;

class SearchController extends Controller
{
    public function searchUsers(Request $request)
    {
        $request->validate([
            'query' => 'required|string|max:100',
            'page' => 'integer|min:1',
            'per_page' => 'integer|min:10|max:100'
        ]);

        $query = $request->input('query');
        $perPage = $request->input('per_page', 30);

        // 执行搜索
        $users = User::search($query, 8) // 阈值设为8
                     ->select('id', 'name', 'email', 'username', 'company', 'user_relevance')
                     ->paginate($perPage);

        return response()->json([
            'results' => $users->items(),
            'pagination' => [
                'total' => $users->total(),
                'page' => $users->currentPage(),
                'per_page' => $users->perPage(),
                'last_page' => $users->lastPage()
            ]
        ]);
    }
}

3. 路由配置

// routes/api.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\SearchController;

Route::get('/search/users', [SearchController::class, 'searchUsers']);

4. 前端调用示例

// 搜索请求函数
async function searchUsers(query) {
  const response = await fetch(`/api/search/users?query=${encodeURIComponent(query)}&per_page=30`);
  const data = await response.json();
  
  // 渲染结果
  renderResults(data.results);
  renderPagination(data.pagination);
}

// 防抖处理
function debounce(func, wait = 300) {
  let timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => func.apply(this, args), wait);
  };
}

// 绑定搜索框事件
document.getElementById('search-input').addEventListener('input', 
  debounce(e => searchUsers(e.target.value))
);

总结与展望

Searchable 为 Laravel 开发者提供了一种简单高效的模型搜索解决方案,通过权重配置、关联查询和相关性排序三大核心功能,轻松实现企业级搜索体验。随着项目发展,建议关注以下方向:

  1. 功能扩展:集成中文分词、拼音搜索等本地化功能
  2. 性能优化:添加查询缓存、结果缓存机制
  3. 接口完善:提供更丰富的搜索参数控制

立即通过以下命令集成到你的项目:

composer require nicolaslopezj/searchable:1.*

收藏本文,关注项目 GitHub 仓库 获取最新更新,下期我们将带来《Searchable 高级实战:多表联合搜索与性能调优》。

如果你觉得本文有帮助,请点赞、收藏、关注三连,你的支持是我们持续创作的动力!

【免费下载链接】searchable A php trait to search laravel models 【免费下载链接】searchable 项目地址: https://gitcode.com/gh_mirrors/se/searchable

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值