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

Laravel预加载关联时限制每个Subcategory的Item数量问题

问题:Laravel预加载关联时限制每个子分类的商品数量为10条

我知道可以限制预加载关联的条目数,但下面的代码达不到预期效果——现在会获取每个subcategory下的所有items,我需要每个存在的subcategory最多只获取10个items。附上相关代码和数据库表结构,求解决办法。

Category::whereHas(
            'subCategories',
            fn($query) => $query->with([
                'items',
                fn($q) => $q->limit(10)
            ])
        )->latest()->get()

数据库表结构

Category表

Schema::create('categories', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('slug');
        $table->string('icon');
        $table->string('description')->nullable();
        $table->timestamps();
    });

Subcategory表

Schema::create('sub_categories', function (Blueprint $table) {
        $table->id();
        $table->foreignIdFor(Category::class)->constrained()->onDelete('restrict');
        $table->string('slug');
        $table->string('name');
        $table->string('description')->nullable();
        $table->string('image_url')->nullable();
        $table->timestamps();
    });

Item表

Schema::create('items', function (Blueprint $table) {
        $table->id();
        $table->foreignIdFor(SubCategory::class)->constrained()->onDelete('restrict');
        $table->string('name');
        $table->string('slug');
        $table->double('amount');
        $table->text('description')->nullable();
        $table->string('image_url');
        $table->integer('hits');
        $table->timestamps();
    });

解决办法

你当前写法的问题在于,with数组里的闭包没有绑定到items关联上,导致limit(10)根本没作用在商品查询上。下面提供几种可行的解决方案:

方案一:修正预加载闭包的写法

把限制闭包直接作为items关联的参数,确保限制逻辑作用到每个子分类的商品查询:

Category::whereHas('subCategories')
    ->with(['subCategories' => function ($subCatQuery) {
        $subCatQuery->with(['items' => function ($itemQuery) {
            $itemQuery->latest()->limit(10); // 可根据需求调整排序规则
        }]);
    }])
    ->latest()
    ->get();

注:Laravel 8及以上版本已优化了预加载关联的limit逻辑,能确保每个子分类独立取10条;如果是更低版本,可能会出现全局只取10条的问题,这时用方案三更稳妥。

方案二:定义带限制的关联方法(推荐)

在SubCategory模型中新增一个专门用于返回限制数量商品的关联方法,代码更清晰:

// app/Models/SubCategory.php
public function limitedItems()
{
    return $this->hasMany(Item::class)->latest()->limit(10);
}

之后查询时直接预加载这个关联即可:

Category::whereHas('subCategories')
    ->with('subCategories.limitedItems')
    ->latest()
    ->get();

方案三:子查询实现精准限制(兼容低版本)

如果遇到低版本Laravel的全局limit问题,用子查询明确筛选每个子分类下的前10条商品ID,确保每个子分类都能拿到自己的10条数据:

Category::whereHas('subCategories')
    ->with(['subCategories' => function ($subCatQuery) {
        $subCatQuery->with(['items' => function ($itemQuery) {
            $itemQuery->whereIn('id', function ($sub) {
                $sub->select('id')
                    ->from('items')
                    ->whereColumn('sub_category_id', 'sub_categories.id')
                    ->latest()
                    ->limit(10);
            });
        }]);
    }])
    ->latest()
    ->get();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:42:25