thinkphp 排序必须用 order() 方法在查询阶段完成,推荐数组写法 ->order(['status' => 'desc', 'create_time' => 'asc']),字段自动转义、支持关联字段;字符串写法易致 sql 注入;用户传参需白名单校验;分页时 url 要透传参数;拖拽排序应维护 sort 字段并建索引。

ThinkPHP 的排序必须在数据库查询阶段用 order() 方法完成,不能靠 PHP 数组后期处理,否则分页错、性能差、关联字段失效。
用数组方式传参最安全
推荐写法:->order(['status' => 'desc', 'create_time' => 'asc'])。字段名自动加反引号,方向值被安全绑定,支持点号字段(如 'user.name')和多字段组合。
- 字符串写法(如
'status desc, create_time asc')不转义字段,用户可控时极易 SQL 注入 - 含关联字段(
with('user'))时,字符串无法解析user.status,会报列不存在错误 - TP5.1 后期及 TP6 全面支持数组语法,兼容性好,语义清晰
用户可选排序字段必须白名单校验
前端传来的 sort_field 和 sort_type 不能直接拼接,需先映射再过滤。
- 定义允许字段:
$allowFields = ['id', 'title', 'status', 'create_time']; - 取参并校验:
$field = in_array(input('sort_field'), $allowFields) ? input('sort_field') : 'id'; - 方向只认
asc/desc:$dir = in_array(input('sort_type'), ['asc','desc']) ? input('sort_type') : 'desc'; - 最终调用:
->order([$field => $dir]),不用Db::raw(),也不拼字符串
带分页时 URL 参数要透传
点击“创建时间”切换升/降序,若不保留当前页码,会跳回第一页。
- 前端链接应带上全部 query 参数,例如:
{:url('index', ['create_time' => $orderRule, 'page' => input('page', 1)])} - 或用
request()->url()提取原 URL,手动注入新排序参数,避免漏掉搜索条件 - 搜索器(如
searchCreateTimeAttr)里只加order(),分页逻辑由控制器统一控制
拖拽排序是另一类场景,别和查询排序混淆
拖拽调整顺序不是靠 order() 实现,而是靠维护一个 sort 字段并批量更新。
- 前端提交完整 ID 数组,如
[7, 2, 9, 1],表示新顺序 - 后端用事务逐条更新:
Db::name('xxx')->where('id', $id)->update(['sort' => $index + 1]) - 查列表时明确写
->order('sort', 'asc'),且给sort字段建索引 - 禁用
order作字段名,改用sort或list_order避免 SQL 关键字冲突
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











