# SkuSpec 服务类使用说明 ## 概述 `SkuSpec` 服务类封装了商品规格相关的所有查询操作,基于 `fa_shop_goods_sku_spec` 和 `fa_shop_spec` 表结构设计。 ## 表结构说明 ### fa_shop_goods_sku_spec (商品SKU规格关联表) ```sql CREATE TABLE `fa_shop_goods_sku_spec` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `goods_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '商品ID', `goods_sku_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'SKU ID', `spec_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '规格ID', `spec_value_id` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '规格值ID', `createtime` bigint(20) DEFAULT NULL COMMENT '添加时间', `updatetime` bigint(20) DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` ### fa_shop_spec (商品规格表) ```sql CREATE TABLE `fa_shop_spec` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(100) NOT NULL DEFAULT '' COMMENT '名称', `type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '规格类型、 1:基础规格 2:定制规格', `createtime` bigint(20) DEFAULT NULL COMMENT '添加时间', `updatetime` bigint(20) DEFAULT NULL COMMENT '更新时间', PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品规格表'; ``` ## 方法说明 ### 1. getSkuAttrs() - 批量获取SKU规格属性字符串 **用途**: 获取多个SKU的规格属性字符串,用于订单显示 **参数**: - `$sku_ids` (array): SKU ID数组 **返回**: - `array`: `[sku_id => 'spec_name:spec_value,spec_name:spec_value']` 格式 **示例**: ```php use app\common\Service\SkuSpec; $sku_ids = [1, 2, 3]; $attrs = SkuSpec::getSkuAttrs($sku_ids); // 返回结果示例: // [ // 1 => '颜色:红色,尺寸:L', // 2 => '颜色:蓝色,尺寸:M', // 3 => '' // 单规格商品返回空字符串 // ] ``` ### 2. getGoodsSkuSpec() - 获取指定商品的SKU信息 **用途**: 获取商品的规格分组信息 **参数**: - `$goods_id` (int): 商品ID **返回**: - `array`: 规格分组数据 **示例**: ```php $specs = SkuSpec::getGoodsSkuSpec(1); // 返回结果示例: // [ // ['id' => 1, 'goods_id' => 1, 'spec_id' => 1], // 颜色规格 // ['id' => 2, 'goods_id' => 1, 'spec_id' => 2] // 尺寸规格 // ] ``` ### 3. getGoodsSpecCombinations() - 获取商品的所有规格组合 **用途**: 获取商品的完整规格组合详情 **参数**: - `$goods_id` (int): 商品ID **返回**: - `array`: 规格组合详情 **示例**: ```php $combinations = SkuSpec::getGoodsSpecCombinations(1); // 返回结果示例: // [ // ['goods_id' => 1, 'spec_id' => 1, 'spec_value_id' => 1, 'spec_name' => '颜色', 'spec_value' => '红色'], // ['goods_id' => 1, 'spec_id' => 1, 'spec_value_id' => 2, 'spec_name' => '颜色', 'spec_value' => '蓝色'], // ['goods_id' => 1, 'spec_id' => 2, 'spec_value_id' => 3, 'spec_name' => '尺寸', 'spec_value' => 'L'], // ['goods_id' => 1, 'spec_id' => 2, 'spec_value_id' => 4, 'spec_name' => '尺寸', 'spec_value' => 'M'] // ] ``` ### 4. getMultiGoodsSpecs() - 获取多个商品的规格信息 **用途**: 批量获取多个商品的规格统计信息 **参数**: - `$goods_ids` (array): 商品ID数组 **返回**: - `array`: 按商品ID分组的规格信息 **示例**: ```php $specs = SkuSpec::getMultiGoodsSpecs([1, 2, 3]); // 返回结果示例: // [ // 1 => [ // ['goods_id' => 1, 'spec_id' => 1, 'spec_name' => '颜色', 'spec_count' => 2], // ['goods_id' => 1, 'spec_id' => 2, 'spec_name' => '尺寸', 'spec_count' => 2] // ], // 2 => [ // ['goods_id' => 2, 'spec_id' => 1, 'spec_name' => '颜色', 'spec_count' => 3] // ] // ] ``` ### 5. findSkuBySpecValues() - 根据规格值查找SKU **用途**: 根据规格值ID组合查找对应的SKU ID **参数**: - `$goods_id` (int): 商品ID - `$spec_value_ids` (array): 规格值ID数组 **返回**: - `int|null`: SKU ID 或 null **示例**: ```php $sku_id = SkuSpec::findSkuBySpecValues(1, [1, 3]); // 红色 + L尺寸 // 返回结果: // 5 (对应的SKU ID) 或 null (未找到匹配的SKU) ``` ### 6. getSpecNameValueMap() - 获取规格名称和值的映射 **用途**: 获取规格的完整映射关系,包含图片等扩展信息 **参数**: - `$spec_ids` (array): 规格ID数组 **返回**: - `array`: 规格映射数据 **示例**: ```php $map = SkuSpec::getSpecNameValueMap([1, 2]); // 返回结果示例: // [ // 1 => [ // 颜色规格 // 1 => ['spec_name' => '颜色', 'spec_value' => '红色', 'image' => 'red.jpg', 'desc' => ''], // 2 => ['spec_name' => '颜色', 'spec_value' => '蓝色', 'image' => 'blue.jpg', 'desc' => ''] // ], // 2 => [ // 尺寸规格 // 3 => ['spec_name' => '尺寸', 'spec_value' => 'L', 'image' => '', 'desc' => ''], // 4 => ['spec_name' => '尺寸', 'spec_value' => 'M', 'image' => '', 'desc' => ''] // ] // ] ``` ### 7. isMultiSpec() - 检查是否为多规格商品 **用途**: 快速判断商品是否有规格 **参数**: - `$goods_id` (int): 商品ID **返回**: - `bool`: true=多规格,false=单规格 **示例**: ```php $isMulti = SkuSpec::isMultiSpec(1); // 返回: true 或 false ``` ### 8. getSpecCount() - 获取商品的规格数量 **用途**: 获取商品有多少种规格类型 **参数**: - `$goods_id` (int): 商品ID **返回**: - `int`: 规格类型数量 **示例**: ```php $count = SkuSpec::getSpecCount(1); // 返回: 2 (表示有颜色和尺寸两种规格) ``` ## 在OrderService中的应用 ### 优化前的代码 ```php // 复杂的多表JOIN查询 $skuAttrCollection = Db::name('shop_goods_sku_spec') ->alias('gss') ->field('gss.goods_sku_id, GROUP_CONCAT(sp.name,":",sv.value ORDER BY sp.id asc) as sku_attr') ->join('shop_spec sp', 'sp.id = gss.spec_id', 'LEFT') ->join('shop_spec_value sv', 'sv.id = gss.spec_value_id', 'LEFT') ->join('shop_goods_sku sku', 'sku.id = gss.goods_sku_id', 'LEFT') ->where('gss.goods_sku_id', 'in', $sku_ids) ->group('gss.goods_sku_id') ->select(); ``` ### 优化后的代码 ```php // 简洁的服务调用 $skuAttrData = \app\common\Service\SkuSpec::getSkuAttrs($sku_ids); ``` ## 使用场景 ### 1. 商品详情页规格展示 ```php // 获取商品的所有规格组合 $specs = SkuSpec::getGoodsSpecCombinations($goods_id); // 按规格分组显示 $groupedSpecs = []; foreach ($specs as $spec) { $groupedSpecs[$spec['spec_name']][] = $spec; } ``` ### 2. 订单商品规格显示 ```php // 批量获取订单中所有SKU的规格属性 $sku_ids = array_column($orderGoods, 'goods_sku_id'); $skuAttrs = SkuSpec::getSkuAttrs($sku_ids); // 在订单列表中显示规格信息 foreach ($orderGoods as &$item) { $item['spec_attr'] = $skuAttrs[$item['goods_sku_id']] ?? ''; } ``` ### 3. 购物车规格匹配 ```php // 用户选择规格后,查找对应的SKU $selectedSpecs = [1, 3]; // 红色 + L尺寸 $sku_id = SkuSpec::findSkuBySpecValues($goods_id, $selectedSpecs); if ($sku_id) { // 找到对应SKU,可以加入购物车 echo "SKU ID: " . $sku_id; } else { // 规格组合不存在 echo "该规格组合不存在"; } ``` ### 4. 商品列表批量处理 ```php // 批量获取多个商品的规格信息 $goods_ids = [1, 2, 3, 4, 5]; $multiSpecs = SkuSpec::getMultiGoodsSpecs($goods_ids); // 标记哪些商品是多规格 foreach ($goodsList as &$goods) { $goods['is_multi_spec'] = isset($multiSpecs[$goods['id']]); $goods['spec_count'] = count($multiSpecs[$goods['id']] ?? []); } ``` ## 性能优势 1. **减少重复代码**: 统一封装规格查询逻辑 2. **优化查询**: 使用批量查询,减少数据库连接 3. **缓存友好**: 结果格式标准化,便于缓存 4. **易于维护**: 规格相关逻辑集中管理 ## 注意事项 1. **数据一致性**: 确保 `goods_sku_id` 字段在所有相关表中保持一致 2. **空值处理**: 单规格商品的规格属性返回空字符串 3. **性能考虑**: 大批量查询时建议分批处理 4. **错误处理**: 方法内部已处理空参数情况,返回空数组或null