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

Laravel 7按关联LISTINGS最新created_at排序GAMES列表问题

解决Laravel中按关联模型最新记录排序并分页的问题

我来帮你搞定这个排序问题~你的当前代码之所以排序不对,核心原因是:leftJoin之后直接groupBy('games.id'),会随机取该游戏关联的某一条Listing的created_at,而不是最新的那一条,自然没法按最新Listing时间正确排序。下面给你两种可行的解决方案:

方案一:使用子查询获取每个游戏的最新Listing时间

这种方式最简洁,通过selectSub给每个Game添加一个latest_listing_created_at字段,存储该游戏对应最新未删除Listing的创建时间,再用这个字段排序:

$games = Game::select('games.*')
    // 子查询:获取每个游戏的最新未删除Listing的创建时间
    ->selectSub(function ($query) {
        $query->selectRaw('MAX(created_at)')
            ->from('listings')
            ->whereColumn('listings.game_id', 'games.id')
            ->whereNull('listings.deleted_at');
    }, 'latest_listing_created_at')
    // 按最新Listing时间倒序,没有Listing的游戏默认排最后
    ->orderByRaw('latest_listing_created_at IS NULL, latest_listing_created_at DESC')
    // 关联加载最新的Listing列表(保持你原有的逻辑)
    ->with(['listings' => function ($query) {
        $query->latest();
    }])
    ->simplePaginate(36);

方案二:先预查询最新Listing记录再关联

如果更习惯用Join的方式,可以先单独查询出每个游戏对应的最新Listing记录,再和Games表关联:

// 先获取每个游戏的最新未删除Listing的创建时间
$latestListings = Listing::select('game_id', DB::raw('MAX(created_at) as latest_created'))
    ->whereNull('deleted_at')
    ->groupBy('game_id');

$games = Game::leftJoinSub($latestListings, 'latest_listings', function ($join) {
    $join->on('games.id', '=', 'latest_listings.game_id');
})
->select('games.*', 'latest_listings.latest_created')
// 同样处理无Listing的游戏排序
->orderByRaw('latest_created IS NULL, latest_created DESC')
->with(['listings' => function ($query) {
    $query->latest();
}])
->simplePaginate(36);

为什么原代码不行?

当你用leftJoin关联Listings后直接groupBy('games.id'),在MySQL关闭ONLY_FULL_GROUP_BY模式的情况下,会随机选取该分组下的一条Listing记录,所以listings.created_at并不是你想要的最新时间,排序逻辑自然失效。而上面两种方案都能精准获取每个游戏对应的最新Listing时间,确保排序正确性。

内容的提问来源于stack exchange,提问作者OMP

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 12:02:29