搜索器不生效的核心原因是调用链断裂或定义不规范:必须在模型中定义严格命名的search+字段驼峰+Attr方法,并在查询时显式调用withSearch(),且其须位于where()后、select()前。

搜索器不生效,核心问题不是代码没写,而是调用链断了或定义方式不对。
搜索器必须显式启用,不会自动触发
TP6 的搜索器不是“监听型”机制,它依赖两个硬性条件:模型里有对应方法 + 查询时主动调用 withSearch()。
只写 searchCreateTimeAttr 方法,但没在查询里加 ->withSearch(['createTime'], $params),它就完全不会运行。
检查模型中搜索器方法命名是否规范
- 方法名必须是
search + 字段驼峰名 + Attr,比如数据库字段是create_time,对应方法是searchCreateTimeAttr -
Attr后缀不能少,大小写必须严格匹配(searchCreatetimeAttr或searchcreatetimeAttr都无效) - 字段名不含下划线时,按标准驼峰规则转换;含下划线(如
api_v2_token)则转为searchApiV2TokenAttr
调用 withSearch 时参数和顺序不能错
- 第一个参数是搜索器字段名数组,如
['status', 'title', 'createTime'] - 第二个参数是原始搜索数据,必须是关联数组,键要和搜索器字段名一致(
'createTime' => ['2024-01-01', '2024-12-31']) - 它必须放在
where()之后、select()之前,因为 TP6 执行顺序是:先跑所有where,再执行withSearch
常见失效场景与修复
立即学习“PHP免费学习笔记(深入)”;
- 用户传了空值(如
title => ''),但搜索器里没判空,直接拼like '%%'导致全表扫描或结果异常 → 在搜索器开头加if (empty($value)) return; - 搜索器内部用了
$query->where(),但实际应传闭包:$query(function ($builder) use ($value) { $builder->where('title', 'like', "%{$value}%"); }); - 外部已用
where('status', 1),搜索器里又写$query(...)->where('status', 2),最终 SQL 是AND status = 1 AND status = 2→ 结果永远为空,应统一逻辑入口,避免冲突 - 多个搜索器混用时性能下降明显 → 只对真正需要处理的字段启用,不用的字段别塞进
withSearch数组
调试建议
- 在搜索器方法里加
trace('searchCreateTimeAttr run');,看是否被调用 - 打印最终 SQL:
$query->buildSql()或开启DB_DEBUG => true查看生成语句 - 确保模型继承的是
think\Model,不是think\db\Query或其他基类
不复杂但容易忽略



















