Laravel关联模型排序问题:如何按Type名称排序Date记录?
按Type名称排序Date记录的Eloquent实现方案
我来帮你搞定这个问题!因为Date和Type之间是通过Tour间接关联的(Date → Tour ↔ Type),咱们需要通过关联查询来实现按Type名称排序Date记录,这里有两种实用的方案:
方案一:使用JOIN语句直接关联排序
这种方式性能较好,适合数据量较大的场景,直接通过SQL JOIN关联中间表和Type表,然后排序:
$dates = Date::select('dates.*') ->join('tours', 'dates.tour_id', '=', 'tours.id') ->join('tour_type', 'tours.id', '=', 'tour_type.tour_id') ->join('types', 'tour_type.type_id', '=', 'types.id') ->orderBy('types.name', 'asc') // 这里按Type名称升序,改成desc就是降序 ->get();
注意:如果你的多对多中间表不是默认的
tour_type(比如自定义了表名),记得替换成实际的表名;另外如果存在一个Tour对应多个Type的情况,这条查询可能会返回重复的Date记录,你可以加上->distinct()去重:$dates = Date::select('dates.*') ->join('tours', 'dates.tour_id', '=', 'tours.id') ->join('tour_type', 'tours.id', '=', 'tour_type.tour_id') ->join('types', 'tour_type.type_id', '=', 'types.id') ->orderBy('types.name', 'asc') ->distinct() ->get();
方案二:使用Eloquent关联加载+排序
如果你更倾向于用Eloquent的关联语法,也可以通过预加载关联,然后利用集合的排序方法,不过这种方式是在内存中排序,适合数据量较小的场景:
$dates = Date::with(['Tour.Types' => function ($query) { $query->orderBy('name', 'asc'); }])->get()->sortBy(function ($date) { // 这里取第一个Type的名称来排序,如果Tour有多个Type,你可以根据需求调整,比如取第一个或者拼接所有名称 return $date->Tour->Types->first()->name ?? ''; });
提示:如果你的Tour可能没有关联的Type,记得加上
?? ''避免报错,或者在查询时过滤掉没有Type的Tour:$dates = Date::whereHas('Tour.Types') ->with(['Tour.Types' => function ($query) { $query->orderBy('name', 'asc'); }])->get()->sortBy(function ($date) { return $date->Tour->Types->first()->name; });
额外优化:添加全局作用域(可选)
如果你的项目中经常需要按Type名称排序Date记录,可以给Date模型添加一个全局作用域,这样每次查询Date时都会自动按Type名称排序:
在Date模型中添加:
protected static function booted() { static::addGlobalScope('sortByTypeName', function ($query) { $query->select('dates.*') ->join('tours', 'dates.tour_id', '=', 'tours.id') ->join('tour_type', 'tours.id', '=', 'tour_type.tour_id') ->join('types', 'tour_type.type_id', '=', 'types.id') ->orderBy('types.name', 'asc') ->distinct(); }); }
这样之后,直接Date::get()就会自动按Type名称排序了。
内容的提问来源于stack exchange,提问作者FarbodKain
相关产品推荐
相关产品推荐

