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
相关产品推荐
相关产品推荐

