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

Laravel关联查询问题:如何实现每个分类取2个品牌、每个品牌取5个指定标签产品

Laravel关联查询实现「每个分类下2个品牌、每个品牌下5个产品」的解决方案

问题原因

你当前的代码中,在with闭包里直接使用limit()会导致全局限制:Laravel预加载关联时,会先查询所有父模型的关联ID,再批量查询关联数据,此时的limit(2)会限制所有分类总共返回2个品牌,limit(5)会限制所有品牌总共返回5个产品,而非每个父模型下的数量限制。

解决方案

以下两种方法可实现「每个分类下2个带标签品牌、每个品牌下5个带标签产品」的需求:


方法一:子查询限制(推荐,性能更优)

通过whereIn结合子查询,为每个父模型单独限制关联数据的数量,避免全局限制问题:

$tagKey = $tag->key;

$categories = Category::where('tagkey', $tagKey)
    ->with(['brands' => function ($query) use ($tagKey) {
        // 每个分类下取前2个带标签的品牌
        $query->where('tagkey', $tagKey)
            ->whereIn('id', function ($subQuery) use ($tagKey) {
                $subQuery->select('id')
                    ->from('brands')
                    ->whereColumn('category_id', 'categories.id') // 关联当前分类ID
                    ->where('tagkey', $tagKey)
                    ->orderBy('id') // 可根据业务需求调整排序字段
                    ->limit(2);
            })
            ->with(['products' => function ($productQuery) use ($tagKey) {
                // 每个品牌下取前5个带标签的产品
                $productQuery->where('tagkey', $tagKey)
                    ->whereIn('id', function ($subQuery) use ($tagKey) {
                        $subQuery->select('id')
                            ->from('products')
                            ->whereColumn('brand_id', 'brands.id') // 关联当前品牌ID
                            ->where('tagkey', $tagKey)
                            ->orderBy('id')
                            ->limit(5);
                    });
            });
    }])
    ->get();

原理:子查询通过whereColumn关联父模型(分类/品牌)的ID,确保每个父模型单独执行一次限制查询,返回该父模型下的前N条关联数据。


方法二:逐个加载关联(适合小数据量场景)

先获取所有符合条件的分类,再逐个为每个分类加载指定数量的品牌,每个品牌加载指定数量的产品:

$tagKey = $tag->key;

// 先获取所有带标签的分类
$categories = Category::where('tagkey', $tagKey)->get();

// 逐个加载每个分类的关联数据
$categories->each(function ($category) use ($tagKey) {
    $category->load([
        'brands' => function ($query) use ($tagKey) {
            // 当前分类下取2个带标签的品牌,并加载其产品
            $query->where('tagkey', $tagKey)->limit(2)->load([
                'products' => function ($productQuery) use ($tagKey) {
                    $productQuery->where('tagkey', $tagKey)->limit(5);
                }
            ]);
        }
    ]);
});

注意:这种方法会产生N+1次查询(N为分类数量),数据量较大时可能影响性能,仅推荐小数据量场景使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:23:19