勾股OA在线文档

order高级排序

可以使用order方法结合case语句进行条件排序。以下示例展示了如何按照销量和上架时间进行动态排序:

use think\facade\Db;

Db::name('goods')
    ->orderRaw("case when sales >= 1000 then 0 else 1 end, putaway_time desc")
    ->select();

在上面的示例中,orderRaw方法使用了原生的SQL表达式,其中包含了case语句。case语句的作用是根据销量进行分类,如果销量超过了1000,则分类为0,否则分类为1。然后按照分类结果进行排序,分类结果相同的再按照上架时间从晚到早排序。

另外,也可以使用orderCase方法对多个字段进行动态排序。例如,以下示例展示了如何按照商品价格和销量进行动态排序:

use think\facade\Db;

Db::name('goods')
    ->orderCase([
        '(price < 50)' => '2', // 如果价格小于50,优先级最高,分类值为2
        '(sales > 1000)' => '1', // 如果销量大于1000,优先级次之,分类值为1
        '1=1' => '0', // 如果都不符合,优先级最低,分类值为0
    ], [
        'price' => 'asc', // 按照价格从低到高排序
        'sales' => 'desc', // 如果价格相同,则按照销量从高到低排序
    ])
    ->select();

在上面的示例中,orderCase方法的第一个参数是一个关联数组,键名是要进行分类的表达式,键值是分类值。如果要同时对多个条件进行判断,可以使用括号将条件括起来,并用逻辑运算符连接。分类值越大,优先级越高。第二个参数和之前的示例一样,表示按照价格和销量进行排序。

需要注意的是,在使用orderRaw或orderCase方法时,要注意安全性问题,避免SQL注入攻击。可以使用Db::raw方法将原生的SQL表达式转义为字符串。
实际使用案例:

    //列表检索
    public function get_list($param = [], $where = [], $whereOr=[])
    {
        $rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
        $now = time();
        $nowa = $now+2678400;
        $list = self::where($where)
            ->where(function ($query) use($whereOr) {
                if (!empty($whereOr)){
                    $query->whereOr($whereOr);
                }
            })
            ->field('a.*, d.title as sign_department,cu.name as customer')
            ->alias('a')
            ->join('department d', 'a.sign_did = d.id','LEFT')
            ->join('customer cu', 'a.customer_id = cu.id','LEFT')
            ->orderRaw("
                CASE 
                    WHEN a.check_status = 0 THEN 1  -- 未提交
                    WHEN a.check_status = 1 THEN 2  -- 审核中
                    WHEN a.end_time < {$now} AND a.end_time>0 AND history_time = 0 THEN 3  -- 到期(基于end_time和history_time判断)
                    WHEN a.end_time > {$now} AND a.end_time < {$nowa} AND a.end_time>0 AND history_time = 0 THEN 4  -- 到期(基于end_time和history_time判断)
                    ELSE 5                  -- 其他(如果有其他状态或不符合上述条件的记录)
                END ASC
            ")
            ->paginate($rows, false, ['query' => $param])
            ->each(function ($item, $key) {
                $item->sign_time = date('Y-m-d', $item->sign_time);
            });
        return $list;
    }