最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
thinkphp排序如何实现条件排序 使用方法介绍
时间:2026-07-12 09:33:52 编辑:袖梨 来源:一聚教程网
ThinkPHP排序需严格校验字段和方向白名单,优先使用关联数组方式(如['status'=>'desc'])防止SQL注入;动态排序须验证用户输入;特殊排序用Db::Expression;paginate前必须调用order且避免全局覆盖。
ThinkPHP 的排序不是简单写个 order() 就完事,关键在于“条件”二字——字段是否可控、方向是否由用户决定、是否涉及关联表或特殊值顺序,都会影响写法和安全性。直接拼字符串最危险,也最容易出错;用数组方式最稳妥,配合白名单校验才能真正落地。
多字段排序:优先用关联数组,别拼字符串
TP6 官方明确推荐用关联数组传参,TP5.1 后期版本也已支持。它自动转义字段名,避免 SQL 注入,语义清晰,还兼容带点号的关联字段(如 'user.status')。
-
正确写法:
->order(['status' => 'desc', 'sort' => 'asc', 'id' => 'desc']) -
错误写法:
->order('status desc, sort asc')—— 字段名没转义,遇上用户输入或反引号缺失,容易报Column not found - 如果字段来自前端(比如
?sort=price&order=desc),必须先校验白名单:$allowFields = ['price', 'name', 'create_time']; $field = in_array($input, $allowFields) ? $input : 'id';
动态排序方向:只认白名单里的 asc/desc
用户传来的 order 参数不能直接拼进 SQL。哪怕只是 "desc",一旦被篡改成 "desc, (SELECT ...)",就可能触发注入。
- 方向值必须严格限制:
$dir = in_array($request->param('order'), ['asc', 'desc']) ? $request->param('order') : 'desc'; - 组合字段与方向时,统一走数组:
->order([$field => $dir]),TP 内部会安全处理 - 千万别用
Db::raw()或字符串拼接,htmlspecialchars()对数据库层无效
特殊排序需求:自定义顺序 or NULL 处理
普通 ASC/DESC 搞不定时,就得上原生片段。比如按指定 ID 顺序排,或把 NULL 值甩到末尾。
立即学习“PHP免费学习笔记(深入)”;
-
按指定值排序:用
Db::Expression构造FIELD()函数$exp = new thinkDbExpression("FIELD(status, 2, 1, 3)");<br>->order($exp) -
控制 NULL 位置:MySQL 中
status IS NULL可当布尔表达式用->orderRaw('status IS NULL, status ASC')(NULL 排最后) - 涉及关联表字段(如
user.name)时,字符串写法基本失效,建议改用view查询或子查询
分页 + 排序常见坑:paginate 会悄悄覆盖你的 order
调了 order() 却没生效?大概率是 paginate() 在背后“补刀”。它默认在无 order 时加 id ASC,但一旦你调过 order()(哪怕空参),它就不再补,也不会保留你之前的设置。
- 确保
order()在paginate()之前调用,且不要在模型initialize()或全局 scope 里硬写$this->order() - 若需默认排序又允许覆盖,封装成方法:
public function listWithOrder($field = 'id', $dir = 'desc') { return $this->order([$field => $dir])->paginate(); } - 分页链接保留排序参数:
['query' => request()->param()],避免点击翻页后排序丢失
相关文章
- DNF18周年庆巫女时装属性怎样选-18周年庆版本DNF巫女时装属性选哪个好 07-20
- 天堂2盟约里巨蚁女王怎么打-天堂2盟约如何击败巨蚁女王 07-20
- 决胜之心 魂镜影介绍 07-20
- 迷你世界炎狱魔龙如何获得 炎狱魔龙技能图鉴 07-20
- 迷你世界厨房修建攻略 迷你世界厨房搭建方法 07-20
- 洛克王国世界s3赛季什么时候开始 07-20