Laravel预加载时如何限制每个漫画的关联章节数量?
解决Laravel预加载时限制每个模型关联记录数量的问题
在Laravel中直接对hasMany关联使用limit()会导致全局限制总记录数,而非每个父模型单独限制。要实现每个漫画获取3个最新章节,可通过以下几种方式解决:
方法一:使用子查询关联(Laravel 8+推荐)
在Komik模型中新增自定义关联方法,通过子查询筛选每个漫画的最新3个章节:
class Komik extends Model { public function genres() { return $this->belongsToMany(Genre::class); } public function chapters() { return $this->hasMany(Chapter::class); } // 新增关联:每个漫画的最新3个章节 public function latestChapters() { return $this->hasMany(Chapter::class) ->select('komik_id', 'number', 'slug') ->orderBy('number', 'desc') // 按number倒序取最新章节 ->limit(3); } }
查询时使用这个新关联,结合withSub实现子查询预加载:
$latestUpdated = Komik::select('id', 'title', 'slug', 'img') ->with([ 'genres' => function ($query) { $query->select('id', 'name', 'slug'); } ]) ->withSub([ 'latestChapters' => function ($query) { $query->select('komik_id', 'number', 'slug') ->orderBy('number', 'desc') ->limit(3); } ], 'latest_chapters') ->latest('updated_at') ->get();
方法二:数据库子查询筛选(兼容低版本Laravel)
如果你的Laravel版本低于8.x,可直接在关联查询中通过子查询锁定每个漫画的3个最新章节:
$latestUpdated = Komik::select('id', 'title', 'slug', 'img') ->with([ 'genres' => function ($query) { $query->select('id', 'name', 'slug'); }, 'chapters' => function ($query) { $query->select('komik_id', 'number', 'slug') ->whereIn('id', function ($subQuery) { $subQuery->select('id') ->from('chapters') ->whereColumn('komik_id', 'komiks.id') ->orderBy('number', 'desc') ->limit(3); }) ->orderBy('number', 'desc'); } ]) ->latest('updated_at') ->get();
该方式先通过子查询筛选出每个漫画的3个最新章节ID,再关联查询对应数据,确保每个漫画独立获取3条记录。
方法三:集合层面处理(仅适合小数据量场景)
如果数据量不大,也可以先预加载所有章节,再在集合中对每个漫画的章节进行截断:
$latestUpdated = Komik::select('id', 'title', 'slug', 'img') ->with([ 'genres' => function ($query) { $query->select('id', 'name', 'slug'); }, 'chapters' => function ($query) { $query->select('komik_id', 'number', 'slug') ->orderBy('number', 'desc'); } ]) ->latest('updated_at') ->get() ->each(function ($komik) { $komik->setRelation('chapters', $komik->chapters->take(3)); });
注意:此方法会加载所有章节数据到内存,数据量大时性能较差,仅适合小数据集场景。
内容的提问来源于stack exchange,提问作者LackFos
相关产品推荐
相关产品推荐

