Yii2中排序需根据场景选择安全方式:单字段用['field'=>SORT_DESC]数组语法;多字段组合按优先级用关联数组;计算字段排序须addSelect声明别名;IN顺序排序用FIELD()函数;GridView默认排序在ActiveDataProvider中配置defaultOrder。

在 Yii2 开发中,需要按利润高低展示商品列表、按置顶+报满+手动序号组合规则排列活动、或严格按传入 ID 数组顺序返回资讯——这些都不是简单写个 orderBy('id DESC') 就能解决的。
基础单字段排序
直接传字符串最省事,但仅适用于无空格、无特殊字符、不需动态方向控制的场景。
使用数组语法更安全,且支持正/逆序明确声明:['created_at' => SORT_DESC]。
这一步操作起来很简单,直接把字段名和方向配对放进数组就行。
【SORT_DESC 和 SORT_ASC 是常量,不能写成 'desc' 或 1】,否则会触发 PHP 警告并导致排序失效。
多字段组合排序
当多个条件共同决定显示顺序时,必须用关联数组明确每个字段的方向,顺序即执行优先级。
第一步:先按是否置顶降序(置顶排最前)→ 第二步:再按是否报满升序(未报满优先)→ 第三步:最后按手动序号升序 → 第四步:同序号则按 ID 降序兜底。
代码写成:->orderBy(['is_top' => SORT_DESC, 'is_full' => SORT_ASC, 'display_order' => SORT_ASC, 'id' => SORT_DESC])。
注意:如果只写 ->orderBy('is_top DESC, is_full ASC') 字符串形式,虽然也能运行,但会绕过 Yii 的 SQL 安全转义,【存在被注入恶意 ORDER BY 子句的风险】。
使用计算字段排序
当排序依据不是原始字段,而是两个字段运算结果(如利润 = 市场价 - 平台价),必须先用 addSelect() 把计算值作为虚拟列引入查询上下文。
方法一:用别名 + addSelect 显式声明计算列$list = Goods::find()->alias('goods')->addSelect(['goods.*', '(goods.market_price - goods.shop_price) AS profit'])->orderBy(['profit' => SORT_DESC])->all();
方法二:不加 addSelect,直接在 orderBy 中写表达式(不推荐)->orderBy([new \yii\db\Expression('(market_price - shop_price) DESC')]) —— 这会导致 SELECT 不包含该表达式,MySQL 可能报错或返回不可预期结果。
按 IN 列表指定顺序排序
前端传入 ID 数组 [3, 1, 2],要求数据库返回结果严格按这个顺序排列,不能依赖主键或时间戳。
使用 MySQL 的 FIELD() 函数是唯一可靠方式。
方法一:用 Query 构建器 + Expression
$ids = [3, 1, 2];<br>
$idsStr = implode(',', $ids);<br>
$query = (new \yii\db\Query())<br>
->select('*')<br>
->from('product')<br>
->where(['in', 'id', $ids])<br>
->orderBy([new \yii\db\Expression("FIELD(id, $idsStr)")]);
方法二:在 ActiveRecord 查询中嵌入 Expression(更常用)$query->orderBy([new \yii\db\Expression("FIELD(`id`, " . implode(',', $ids) . ")")]);
⚠️ 必须确保 $ids 是整型数组且已过滤,否则拼接进 SQL 会引发注入漏洞。
设置 GridView 默认排序
用户首次打开数据列表页时,不点任何表头就应按合理顺序展示(如最新创建的排最前),而不是默认按主键正序。
找到搜索模型中的 search() 方法,在构建 ActiveDataProvider 时注入 sort 配置项。
修改前:$dataProvider = new ActiveDataProvider(['query' => $query]);
修改后:$dataProvider = new ActiveDataProvider(['query' => $query, 'sort' => ['defaultOrder' => ['created_at' => SORT_DESC]]]);
这会覆盖框架默认的 id ASC 行为,且不影响用户后续点击表头触发的自定义排序逻辑。


















