tp5模糊查询
ThinkPHP5的模糊模糊查询,说穿了就是查询like操作。但很多人写出来的模糊代码,要么慢得要命,查询要么漏洞百出。模糊我见过太多新手直接拼字符串进SQL,查询然后被注入教做人。模糊今天不扯虚的查询,直接看几个实战片段。模糊
最基础的查询写法,用where方法的模糊数组形式。比如搜用户名带“张”的查询,where('username',模糊 'like', '%张%'),这没问题。查询但你要是模糊搜的关键词本身含百分号或下划线,比如用户搜了“50%off”,那乐子就大了——like会把%当通配符,结果全表匹配,返回一堆莫名其妙的数据。得转义,用addslashes或者手动替换\%和\_才行。
更隐蔽的坑在性能上。%关键词%这种写法,数据库索引直接失效,全表扫描跑不掉。表里就几千条数据无所谓,可一旦到了百万级,一个模糊查询能把数据库拖到超时。我接手过一个后台管理项目,用户列表搜索框输入任意字符,响应时间从2秒涨到30秒,最后定位就是这条like语句。解决方案也不复杂,如果业务允许,改成关键词%前缀匹配,至少能走索引。要是非中间匹配不可,那就上全文索引或者考虑Elasticsearch,别硬扛。
TP5里还有个容易被忽略的点,就是whereLike方法。它本质和where('field', 'like', ...)一样,但配合value方法使用时,会自动处理一些边界情况。比如你写whereLike('name', $kw),如果你传的$kw是空字符串,TP5不会生成like '%%'这种无效条件,直接跳过。但你要是自己拼字符串,空值就会变成where name like '%%',查出来全表,还慢,逻辑还错。细节决定成败,框架提供的封装不是摆设。
再一个实战经验,多字段模糊查询。比如搜索框同时匹配用户名和邮箱,新手喜欢写where('username|email', 'like', '%'.$kw.'%')。这语法TP5确实支持,但生成的SQL是(username like '%kw%' OR email like '%kw%'),两个字段都扫,性能更差。更合理的做法是分开查,再用union合并结果集,或者干脆先查一个字段,命中少就返回,命中多再做二次筛选。别嫌麻烦,数据量大了你就知道这有多香。
最后提个安全习惯。所有用户输入进like之前,强制过滤特殊字符。别依赖框架的自动转义,TP5的查询构造器确实会预处理参数,但like里的%和_是漏网之鱼。我通常写个私有方法,把关键词里的%、_、\\全部替换成转义版本,再丢给查询。这样既防注入,又防通配符误判,双保险。
模糊查询看着简单,用好了是功能,用不好是灾难。多想想数据量、索引、边界输入,比背语法有用得多。
