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

