Laravel 7.2多表查询问题:点击分类按钮获取对应已下单商品
解决Laravel中分类下已下单商品的查询问题
嘿,我完全懂你卡壳的感觉——刚接触Laravel关联查询的时候,把两个单独的筛选逻辑揉到一起确实容易懵。咱们先把问题拆解清楚,然后一步步搞定它:
先修正模型里的小问题
首先注意到你的Product模型里的orders关联写错了!因为Product和Order是多对多关系(通过order_product中间表),所以应该用belongsToMany而不是belongsTo,不然关联查询会出错:
// Product模型修正后的orders关联 class Product extends Model { public function categories() { return $this->belongsToMany('App\Category'); } public function orders() { // 如果中间表有额外字段,可添加->withPivot(...)来获取 return $this->belongsToMany('App\Order'); } }
方案一:用Eloquent关联查询(推荐,更符合Laravel风格)
我们可以直接从Product模型出发,同时添加两个筛选条件:
- 商品属于指定分类(通过
whereHas('categories')) - 该商品被当前用户下单过(通过
whereHas('orders'))
代码示例:
// 获取当前用户ID(假设用户已登录,可根据实际场景调整) $user_id = auth()->id(); // 获取请求中的分类slug $category_slug = request()->category; $products = Product::with('categories') // 预加载分类,避免N+1查询问题 // 筛选属于目标分类的商品 ->whereHas('categories', function ($query) use ($category_slug) { $query->where('slug', $category_slug); }) // 筛选当前用户已下单的商品 ->whereHas('orders', function ($query) use ($user_id) { $query->where('orders.user_id', $user_id); }) ->get();
这个方法完全利用Laravel的Eloquent关联特性,代码简洁易维护,还能自动处理重复数据。
方案二:用DB查询构建器(贴合你之前的写法)
如果你更习惯原生查询构建器的方式,可以把两个查询逻辑合并,通过多表关联实现:
$user_id = auth()->id(); $category_slug = request()->category; $products = DB::table('order_product') ->join('products', 'order_product.product_id', '=', 'products.id') ->join('category_product', 'products.id', '=', 'category_product.product_id') ->join('categories', 'category_product.category_id', '=', 'categories.id') // 筛选当前用户的订单 ->where('order_product.user_id', '=', $user_id) // 筛选目标分类 ->where('categories.slug', '=', $category_slug) // 按需选择需要的字段,避免冗余 ->select('products.*', 'categories.name as category_name', 'categories.slug') ->distinct() // 防止同一个商品在多个订单中出现导致重复结果 ->get();
为什么之前的方法行不通?
你之前是分开查询“分类下的商品”和“已下单商品”,但没有把两个条件合并到同一个查询里。现在的核心是要让查询同时满足属于指定分类和被该用户下单这两个条件,所以需要把两个筛选逻辑整合到一起。
内容的提问来源于stack exchange,提问作者Kuze
相关产品推荐
相关产品推荐

