laravel 没有 wherelike 方法,因其仅为 where($column, 'like', $value) 的冗余语法糖;正确做法是显式使用 where + like + 手动控制通配符位置,并用闭包分组多字段 or 条件,同时校验输入、注意字段类型与分页位置。

whereLike 不是 Laravel 原生方法,直接调用会报 Call to undefined method Illuminate\Database\Query\Builder::whereLike()。别费劲找包或写宏——用标准 where() 配合 'like' 操作符就能安全、清晰地实现,且无需额外依赖。
为什么没有 whereLike 方法
Laravel 查询构造器(包括 Eloquent 和 Query Builder)从未内置 whereLike。社区偶尔有人封装成宏或 trait,但官方不提供,原因很实际:
- 它只是
where($column, 'like', $value)的语法糖,无语义增益 - 加一层封装反而模糊了 SQL 本质,新人误以为它是“特殊模糊函数”,忽略通配符位置和索引影响
- 容易诱导写出
whereLike('name', $q)这种不带%的错误,结果查不到数据还找不到原因
正确写法:where + like + 手动控制通配符
所有模糊匹配都应显式决定通配符位置,这直接影响性能和语义:
-
where('title', 'like', "%{$q}%")→ 全模糊(前后可变),无法走 B-tree 索引,大数据量慎用 -
where('title', 'like', "{$q}%")→ 前缀匹配,能命中索引,适合搜索建议、品牌名等 -
where('title', 'like', "%{$q}")→ 后缀匹配,MySQL 8.0+ 可用反向索引优化,但需手动建 - 永远不要拼
"%{$q}%"进whereRaw()——whereRaw('title LIKE ?', ["%{$q}%"])是错的,?不会自动包裹通配符,得自己加
多字段 OR 模糊必须用闭包分组
这是线上最常翻车的点。下面这段代码看着合理,实际逻辑崩坏:
$users = User::where('name', 'like', "%{$q}%")
->orWhere('email', 'like', "%{$q}%")
->where('status', 1)
->get();
生成的 SQL 等价于:WHERE (name LIKE ?) OR (email LIKE ?) AND (status = 1),即 status 只约束 email 匹配项。正确写法是:
- 把所有
orWhere放进一个where()闭包里 - 非模糊条件(如
status、deleted_at)写在闭包外 - 关联字段模糊用
orWhereHas(),同样要包进同一闭包
例如:
$users = User::where('status', 1)
->where(function ($q) use ($q) {
$q->where('name', 'like', "%{$q}%")
->orWhere('email', 'like', "%{$q}%")
->orWhereHas('profile', fn ($sub) => $sub->where('bio', 'like', "%{$q}%"));
})
->get();
空值、类型与分页的连环坑
搜索接口上线后暴雷,往往不是模糊逻辑本身,而是边缘情况没守好门:
-
$request->input('q')可能是null、空字符串、纯空白字符——直接塞进where()会导致查出全表或报错,必须用$request->filled('q')校验 - 用户搜
123,但字段是字符串型(如订单号),where('order_no', $q)会被 MySQL 隐式转成数字,123A就匹配失败;模糊查就不存在这问题,但得确认字段类型是否真该模糊 -
paginate()必须放在整个查询链最后,哪怕你加了selectRaw()或withCount(),只要它不在末尾,COUNT(*) 就漏条件,分页数就不准
真正难的从来不是“怎么写 like”,而是想清楚:这个搜索到底要解决什么问题?要不要支持分词?要不要相关性排序?百万级数据还硬扛 LIKE '%xxx%',不如早切 Scout + Meilisearch——模糊只是入口,不是终点。











