ThinkPHP 6 的 whereLike 需链式调用后接 paginate(),推荐前缀匹配(如 '张三%')以利用索引;关键词须 trim 清洗、转义特殊字符,并通过 appends(['keyword' => input('keyword')]) 透传参数防翻页丢失。

ThinkPHP 6 的 whereLike 怎么配合分页用
直接在查询链式调用里加 whereLike,再接 paginate() 就行,但要注意字段名和通配符位置。比如搜索用户昵称含“张三”:
-
whereLike('nickname', '%张三%')是常用写法,但数据库索引可能失效;更推荐whereLike('nickname', '张三%')(前缀匹配)来利用索引 - 如果字段是 JSON 类型或需要模糊多字段,得改用
whereRaw,例如whereRaw("JSON_CONTAINS(profile, '"张三"')") -
paginate()默认每页 15 条,想改就传参:paginate(20),别漏掉参数类型必须是 int
关键词带空格或特殊字符时分页失效怎么办
用户搜“PHP 开发”,空格会让 whereLike 匹配失败;搜“user.name”可能被误解析为字段路径。核心是提前清洗和转义:
- 用
trim()去首尾空格,再用str_replace([' ', ' '], '%', $keyword)把中文/英文空格都换成通配符 - 对单引号、百分号、下划线这些
LIKE元字符,必须用escape参数处理:whereLike('title', "%{$keyword}%", 'utf8mb4', '\'),然后在like前加ESCAPE '\' - 如果用了
withSearch或自定义搜索器,记得在搜索器里统一做清洗,否则分页对象拿到的是原始脏数据,render()生成的 URL 会把未编码的空格变成%20,导致翻页时关键词丢失
分页链接里的关键词参数没保留,点第二页就变空搜索
这是最常踩的坑:ThinkPHP 的 paginate() 默认只保留当前请求的 page 参数,其他如 keyword 需手动追加。
- 模板里不能直接写
{$list->render()},得改成:{$list->appends(['keyword' => input('keyword')])->render()} - 如果关键词来自 POST,得先存到 session 或重定向为 GET,因为
appends只处理查询参数 - 多个搜索条件(如 category、status)要一并
appends,漏一个,翻页后那个条件就归零了
搜索结果少但分页显示 100 页?缓存或 count 查询出错了
分页总数靠 count() 算,而 whereLike 在大数据量下容易让 MySQL 用错索引,导致 count 慢甚至不准。
立即学习“PHP免费学习笔记(深入)”;
- 检查 SQL 日志,看
SELECT COUNT(*)是否走了索引;没走的话,在模糊字段上建前缀索引:ALTER TABLE user ADD INDEX idx_nickname (nickname(32)) - 避免在
count()里用JOIN或子查询,ThinkPHP 6.1+ 支持paginate(['query' => ['keyword' => $k]])自动透传,但底层仍会执行完整 count,大表建议用估算:paginate(15, false, ['total' => $estimatedCount]) - 如果用了 Redis 缓存分页数据,注意
keyword必须作为缓存 key 的一部分,比如'search_user_' . md5($keyword),否则不同关键词共用一个缓存,结果串了
关键词搜索分页真正的复杂点不在写法,而在数据一致性——从输入清洗、SQL 执行、总数计算到 URL 参数透传,每个环节断了,用户点下一页就丢上下文。尤其上线后加了缓存或读写分离,更要验一遍关键词是否还随分页链路完整传递。



















