Laravel 5.5中如何按价格区间及属性筛选商品?
正确实现Laravel 5.5商品价格区间与属性筛选的方案
嘿,我仔细看了你的需求和写的代码,发现几个需要调整的地方,咱们一步步把这个筛选功能捋顺:
先明确几个关键问题
- 字段名不匹配:数据库关联表的字段是
attribute_id、attribute_value_id,但你代码里用了att_id、sub_att_id,这会直接导致查询失败 whereHas闭包写法有误:不能在闭包里再调用->atts(),应该直接对关联关系添加条件- 请求参数处理不严谨:未判断
min_price/max_price是否存在,容易引发报错 - 代码过于紧凑:可读性差,后续维护难度高
第一步:确认模型关联是否正确
首先要确保Product模型和属性相关模型的关联逻辑正确,假设你的模型命名为Product、Attribute、AttributeValue,在Product模型中添加关联:
// app/Product.php public function attributeValues() { // 关联属性值表,通过中间表attribute_product_attribute_value return $this->belongsToMany(AttributeValue::class, 'attribute_product_attribute_value', 'product_id', 'attribute_value_id') ->withPivot('attribute_id', 'value'); // 带上中间表的额外字段 } // 如果需要直接关联属性表,可添加这个方法 public function attributes() { return $this->belongsToMany(Attribute::class, 'attribute_product_attribute_value', 'product_id', 'attribute_id') ->withPivot('attribute_value_id', 'value'); }
第二步:重构筛选逻辑
把价格筛选和属性筛选拆分处理,同时做好参数校验,避免异常:
// 获取分类(修正了原代码的换行和语法问题) $category = CategoryProduct::getCategoryByValue('id', decode(request()->input('category'))); if (!$category) { // 分类不存在时返回空集合,可根据业务调整逻辑 $products = collect(); } else { // 初始化查询构造器 $query = $category->products(); // 处理价格区间筛选:给参数设置默认值,避免无参数时报错 $minPrice = (int)request()->input('min_price', 0); $maxPrice = (int)request()->input('max_price', PHP_INT_MAX); $query->whereBetween('price', [$minPrice, $maxPrice]); // 处理属性筛选 $attFilters = request()->input('att_filter', []); if (!empty($attFilters)) { $query->whereHas('attributeValues', function ($q) use ($attFilters) { foreach ($attFilters as $attributeId => $valueIds) { // 假设att_filter的结构是 [属性ID => [属性值ID1, 属性值ID2,...]] $q->wherePivot('attribute_id', decode($attributeId)) ->whereIn('attribute_value_id', array_map('decode', $valueIds)); } }, '=', count($attFilters)); // 确保所有属性条件都满足(AND关系) } // 执行查询 $products = $query->get(); }
关键细节说明
- 价格区间:用
whereBetween比两个where更简洁,同时给参数设置默认值,避免无参数时的报错 - 属性筛选:
- 使用
whereHas的第三个参数=, count($attFilters),确保商品满足所有选中的属性条件(即“且”的关系) - 假设你的
att_filter提交结构是[属性ID => [属性值ID集合]],如果是单选场景,可把whereIn改成where - 对每个属性ID和属性值ID都做
decode处理,和你原代码的逻辑保持一致
- 使用
- 代码可读性:拆分逻辑后更容易维护,后续新增筛选条件也更方便
内容的提问来源于stack exchange,提问作者Saeid Zare
相关产品推荐
相关产品推荐

