You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel Eloquent关联排序问题:按预订日期及CRT用户名排序

解决Laravel集合按预订日期+关联用户姓名排序的问题

看起来你现在的查询已经实现了按booked_on降序排列预订记录,但同日期下的用户姓名排序没生效——这是因为你在users关联里加的orderBy只是给关联的用户集合排序,并没有影响到bookings本身的排序顺序。

下面给你两种可行的解决方案:

方案一:查询层面通过关联表排序(推荐)

你可以在bookings的查询闭包里,通过join关联到crts和users表,直接基于用户姓名进行排序。这样数据库层面就能完成排序,性能更好:

$schoolBookings = SchoolModel::with([
        'bookings.crts', 
        'bookings.crts.users' => function($que) { 
            $que->orderBy('first_name', 'ASC'); 
        }, 
        'schoolType', 
        'bookings.crts.teachingSpecializations', 
        'bookings' => function($que) use($filters, $input) { 
            if (!empty($input['start_date'])) { 
                $que->where('booked_on', '>=', $input['start_date']); 
            } 
            if (!empty($input['end_date'])) { 
                $que->where('booked_on', '<=', $input['end_date']); 
            } 
            $que->where('booked_on', '<=', date("Y-m-d 00:00:00"));
            
            // 新增关联join和排序逻辑
            $que->join('crts', 'bookings.crt_id', '=', 'crts.id') // 请根据实际表关联字段调整外键
                ->join('users', 'crts.user_id', '=', 'users.id') // 请根据实际表关联字段调整外键
                ->orderBy('booked_on', 'desc')
                ->orderBy('users.first_name', 'asc')
                ->select('bookings.*'); // 指定选择bookings字段,避免多表字段冲突
        },
    ])
    ->where(function($que) use ($filters, $schoolId) { // 补充$schoolId到use参数中
        if (!empty($schoolId)) { 
            $que->where('id', $schoolId); 
        } 
    })
    ->get()
    ->toArray();

注意:请根据你实际的数据库表关联字段,调整join语句里的外键(比如bookings.crt_id、crts.user_id),确保和你的表结构一致。

方案二:集合层面排序

如果不想修改查询逻辑,也可以在获取集合后,对每个学校的bookings集合进行自定义排序,适合数据量不大的场景:

$schoolBookings = SchoolModel::with([
        'bookings.crts', 
        'bookings.crts.users' => function($que) { 
            $que->orderBy('first_name', 'ASC'); 
        }, 
        'schoolType', 
        'bookings.crts.teachingSpecializations', 
        'bookings' => function($que) use($filters, $input) { 
            if (!empty($input['start_date'])) { 
                $que->where('booked_on', '>=', $input['start_date']); 
            } 
            if (!empty($input['end_date'])) { 
                $que->where('booked_on', '<=', $input['end_date']); 
            } 
            $que->where('booked_on', '<=', date("Y-m-d 00:00:00"));
            $que->orderBy('booked_on', 'desc');
        },
    ])
    ->where(function($que) use ($filters, $schoolId) {
        if (!empty($schoolId)) { 
            $que->where('id', $schoolId); 
        } 
    })
    ->get()
    ->map(function($school) {
        // 对当前学校的bookings进行自定义排序
        $school->bookings = $school->bookings->sort(function($a, $b) {
            // 先比较预订日期(降序)
            $dateCompare = strcmp($b->booked_on, $a->booked_on);
            if ($dateCompare !== 0) {
                return $dateCompare;
            }
            // 日期相同则比较用户first_name(升序)
            $userA = $a->crts->first()->users->first()->first_name ?? '';
            $userB = $b->crts->first()->users->first()->first_name ?? '';
            return strcmp($userA, $userB);
        })->values(); // 重置集合键值,避免索引混乱
        return $school;
    })
    ->toArray();

测试任意一种方案,都能得到你想要的排序结果:先按预订日期倒序排列,同日期下按用户姓名字母升序排列。

内容的提问来源于stack exchange,提问作者Pradeep Kumar Rajput

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:52:57