SkuSpec_使用说明.md 8.0 KB

SkuSpec 服务类使用说明

概述

SkuSpec 服务类封装了商品规格相关的所有查询操作,基于 fa_shop_goods_sku_specfa_shop_spec 表结构设计。

表结构说明

fa_shop_goods_sku_spec (商品SKU规格关联表)

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 (商品规格表)

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'] 格式

示例:

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: 规格分组数据

示例:

$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: 规格组合详情

示例:

$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分组的规格信息

示例:

$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

示例:

$sku_id = SkuSpec::findSkuBySpecValues(1, [1, 3]); // 红色 + L尺寸

// 返回结果: 
// 5 (对应的SKU ID) 或 null (未找到匹配的SKU)

6. getSpecNameValueMap() - 获取规格名称和值的映射

用途: 获取规格的完整映射关系,包含图片等扩展信息

参数:

  • $spec_ids (array): 规格ID数组

返回:

  • array: 规格映射数据

示例:

$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=单规格

示例:

$isMulti = SkuSpec::isMultiSpec(1);
// 返回: true 或 false

8. getSpecCount() - 获取商品的规格数量

用途: 获取商品有多少种规格类型

参数:

  • $goods_id (int): 商品ID

返回:

  • int: 规格类型数量

示例:

$count = SkuSpec::getSpecCount(1);
// 返回: 2 (表示有颜色和尺寸两种规格)

在OrderService中的应用

优化前的代码

// 复杂的多表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();

优化后的代码

// 简洁的服务调用
$skuAttrData = \app\common\Service\SkuSpec::getSkuAttrs($sku_ids);

使用场景

1. 商品详情页规格展示

// 获取商品的所有规格组合
$specs = SkuSpec::getGoodsSpecCombinations($goods_id);

// 按规格分组显示
$groupedSpecs = [];
foreach ($specs as $spec) {
    $groupedSpecs[$spec['spec_name']][] = $spec;
}

2. 订单商品规格显示

// 批量获取订单中所有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. 购物车规格匹配

// 用户选择规格后,查找对应的SKU
$selectedSpecs = [1, 3]; // 红色 + L尺寸
$sku_id = SkuSpec::findSkuBySpecValues($goods_id, $selectedSpecs);

if ($sku_id) {
    // 找到对应SKU,可以加入购物车
    echo "SKU ID: " . $sku_id;
} else {
    // 规格组合不存在
    echo "该规格组合不存在";
}

4. 商品列表批量处理

// 批量获取多个商品的规格信息
$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