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

Laravel 9 多分类ID关联商品展示问题求助

问题描述

我正在使用Laravel 9搭建电商系统,其余功能运行正常,但遇到一个问题:商品表的cat_id字段存储多个分类ID(格式如1,2,),现点击“News”分类(ID为2)时,希望展示关联的2个商品,当前控制器代码无法实现该需求,以下是我的表结构与控制器代码:

商品表:

|---ID---|---Name---|---Cat_id---|---Status--|
|   1    | T-shirts |    1,2,    |   active  |
|   2    | Pants    |    4,3,    |   active  |
|   3    | Sweaters |    5,2,    |   active  |

分类表

|---ID---|---Name---|
|   1    | General  |
|   2    | News     |
|   3    | Festival |
|   4    | Category |

控制器代码

public function category($slug)
{
    //
    $cat = Category::where('slug', $slug)->first();

    $products = Product::whereIn('cat_id', [$cat->id])->where('status', 'active')->orderby('id', 'asc')->paginate('12');

    return view('frontend/Catproducts', compact('products', 'cat'));
}

请问如何修改代码实现该需求?


解决方案

当前代码无法生效的核心原因:cat_id是带末尾逗号的逗号分隔字符串,而whereIn是做精确值匹配,自然无法命中包含目标分类ID的记录。以下两种方案可解决问题:

方法一:临时修复(适配现有表结构)

利用MySQL的FIND_IN_SET函数匹配字符串中的ID,同时处理cat_id末尾的多余逗号:

public function category($slug)
{
    $cat = Category::where('slug', $slug)->firstOrFail(); // 用firstOrFail避免空值报错

    $products = Product::whereRaw("FIND_IN_SET(?, TRIM(TRAILING ',' FROM cat_id))")
        ->addBinding($cat->id)
        ->where('status', 'active')
        ->orderBy('id', 'asc')
        ->paginate(12);

    return view('frontend/Catproducts', compact('products', 'cat'));
}

TRIM(TRAILING ',' FROM cat_id)会移除cat_id字段末尾的逗号,让FIND_IN_SET能正确识别其中的分类ID。

方法二:重构表结构(推荐长期方案)

逗号分隔存储关联ID属于反范式设计,会导致查询效率低、维护成本高,更合理的做法是建立多对多关联的中间表:

1. 创建product_category中间表

|---product_id---|---category_id---|
|       1        |        1        |
|       1        |        2        |
|       2        |        4        |
|       2        |        3        |
|       3        |        5        |
|       3        |        2        |

2. 定义模型关联

在Product模型中添加关联:

public function categories()
{
    return $this->belongsToMany(Category::class, 'product_category');
}

在Category模型中添加关联:

public function products()
{
    return $this->belongsToMany(Product::class, 'product_category');
}

3. 修改控制器代码

public function category($slug)
{
    $cat = Category::where('slug', $slug)->firstOrFail();

    $products = $cat->products()
        ->where('status', 'active')
        ->orderBy('id', 'asc')
        ->paginate(12);

    return view('frontend/Catproducts', compact('products', 'cat'));
}

这种方式符合Laravel的关联模型设计规范,查询效率更高,后续功能扩展也更便捷。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 02:40:41