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

如何在Laravel中通过多对多关联获取会员关联的品牌?

优化获取会员关联品牌的实现方案

你的代码确实能得到目标品牌集合,但可以通过更简洁高效的方式实现,以下几种方案供参考:

方案一:在Member模型中直接定义关联关系

利用Eloquent的关联特性,直接从Member模型获取关联品牌,避免后续循环遍历:

方式1:自定义多层关联

在Member模型中添加如下关联,通过两层中间表间接关联品牌:

public function brands()
{
    return $this->belongsToMany(
        Brand::class,
        'member_merchandise_categories',
        'member_id',
        'merchandise_category_id'
    )->through('merchandise_categories');
}

该方式利用Laravel的through方法,自动处理「会员-商品分类-品牌」的关联链路,并且会自动去重重复品牌。

使用时直接调用:

$brands = Member::find(Auth::user()->member_id)->brands;

方式2:使用hasManyThrough

如果更习惯链式关联的写法,也可以用hasManyThrough实现:

public function brands()
{
    return $this->hasManyThrough(
        Brand::class,
        MerchandiseCategory::class,
        'id',
        'id',
        'id',
        'merchandise_category_id'
    )->distinct();
}

注意要加上distinct()确保品牌不重复,使用方式和上面一致。

方案二:优化现有集合处理逻辑

如果不想修改模型关联,可利用Laravel集合的高阶函数简化遍历代码:

$member = Member::where('id', Auth::user()->member_id)->with('merchandise_categories.brands')->first();
$brands = $member->merchandise_categories->flatMap(fn($cat) => $cat->brands)->unique('id');

用flatMap直接扁平化所有分类下的品牌集合,再通过unique('id')去重,代码更简洁。

方案三:直接使用查询构建器(高性能场景)

如果数据量较大,追求最高性能,可直接用DB门面构建原生风格查询,减少Eloquent对象实例化开销:

$brands = DB::table('brands')
    ->join('brand_merchandise_categories', 'brands.id', '=', 'brand_merchandise_categories.brand_id')
    ->join('merchandise_categories', 'brand_merchandise_categories.merchandise_category_id', '=', 'merchandise_categories.id')
    ->join('member_merchandise_categories', 'merchandise_categories.id', '=', 'member_merchandise_categories.merchandise_category_id')
    ->where('member_merchandise_categories.member_id', Auth::user()->member_id)
    ->select('brands.*')
    ->distinct()
    ->get();

该方式生成单条SQL查询,仅获取所需数据,性能最优。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 20:57:10