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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:13:30