PHP商品SKU怎么设计表

wen PHP项目 4

本文目录导读:

PHP商品SKU怎么设计表

  1. 方案一:标准SKU(SPU + SKU 模式)—— 最推荐
  2. 方案二:简化版(单表)—— 适合小型项目
  3. 方案三:极简字符串拼键(HashMap思路)
  4. 方案四:EAV表结构(最灵活,适合超多规格或自定义属性)
  5. 关键设计考虑点
  6. 总结推荐

设计商品SKU(Stock Keeping Unit,库存量单位)是电商系统的核心,PHP后端设计表时,关键在于数据结构要支持多规格组合、库存管理和价格区分

以下是电商系统中常用的SKU设计方案,从标准方案进阶优化,附带MySQL建表语句和PHP逻辑示例。


标准SKU(SPU + SKU 模式)—— 最推荐

这是目前最主流的方案,核心思路是:SPU(商品)表 存商品公共信息,SKU表 存具体的规格和库存。

商品表 (spu)

CREATE TABLE `spu` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '商品ID', VARCHAR(200) NOT NULL COMMENT '商品标题',
  `sub_title` VARCHAR(500) DEFAULT '' COMMENT '副标题/卖点',
  `main_image` VARCHAR(255) NOT NULL COMMENT '主图URL',
  `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态:1上架,0下架',
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';

规格属性组表 (spec_group) —— 可选,用于分类管理

CREATE TABLE `spec_group` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `spu_id` INT UNSIGNED NOT NULL COMMENT '所属商品ID',
  `spec_name` VARCHAR(50) NOT NULL COMMENT '规格名,如:颜色、尺码',
  PRIMARY KEY (`id`),
  KEY `idx_spu` (`spu_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

规格属性值表 (spec_value) —— 可选,用于记录该商品的规格选项

CREATE TABLE `spec_value` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `group_id` INT UNSIGNED NOT NULL COMMENT '所属规格组ID',
  `value_name` VARCHAR(50) NOT NULL COMMENT '规格值,如:红色、XL',
  PRIMARY KEY (`id`),
  KEY `idx_group` (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

核心:SKU库存表 (sku) —— 最关键的表

CREATE TABLE `sku` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `spu_id` INT UNSIGNED NOT NULL COMMENT '所属SPU ID',
  `sku_code` VARCHAR(32) NOT NULL COMMENT '商家编码/货号',
  `spec_info` JSON NOT NULL COMMENT '规格信息,JSON格式,例:{"颜色":"红色","尺码":"XL"}',
  `price` DECIMAL(10,2) NOT NULL COMMENT '售价',
  `cost_price` DECIMAL(10,2) DEFAULT '0.00' COMMENT '成本价',
  `stock` INT NOT NULL DEFAULT '0' COMMENT '库存数量',
  `alert_stock` INT DEFAULT '0' COMMENT '库存预警值',
  `sku_image` VARCHAR(255) DEFAULT '' COMMENT 'SKU专属图片(可选)',
  `weight` DECIMAL(8,2) DEFAULT '0.00' COMMENT '重量(kg)',
  `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态:1启用,0停用',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_spu_spec` (`spu_id`, `spec_info`), -- 注意评估是否使用JSON唯一索引(MySQL 8.0支持),或使用序列化字符串
  KEY `idx_spu` (`spu_id`),
  KEY `idx_code` (`sku_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='SKU库存表';

PHP处理逻辑示例:

<?php
// 假设前端传来:颜色=红色,尺码=XL
$specs = ['颜色' => '红色', '尺码' => 'XL'];
// 存入数据库时,序列化为JSON
$spec_json = json_encode($specs, JSON_UNESCAPED_UNICODE);
// 查询时,根据规格组合获取SKU
$query = "SELECT * FROM sku WHERE spu_id = ? AND spec_info = ?";
$stmt = $pdo->prepare($query);
$stmt->execute([$spu_id, $spec_json]);
$sku = $stmt->fetch();
?>

简化版(单表)—— 适合小型项目

如果规格较少(例如只有1-2个维度),将规格直接作为字段存入商品表。

商品表 (product)

CREATE TABLE `product` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(200) NOT NULL,
  `spec_type` VARCHAR(50) DEFAULT NULL COMMENT '规格1名称,如:颜色',
  `spec_value1` VARCHAR(50) DEFAULT NULL COMMENT '规格1值,如:红色',
  `spec_type2` VARCHAR(50) DEFAULT NULL COMMENT '规格2名称,如:尺码',
  `spec_value2` VARCHAR(50) DEFAULT NULL COMMENT '规格2值,如:XL',
  `price` DECIMAL(10,2) NOT NULL,
  `stock` INT NOT NULL,
  `image` VARCHAR(255) DEFAULT '',
  -- 其余字段...
  KEY `idx_spec1` (`spec_value1`),
  KEY `idx_spec2` (`spec_value2`)
) ENGINE=InnoDB;

缺点:无法灵活扩展规格数量;查询时条件复杂;库存管理困难,仅适合纯新手或者一次性项目。


极简字符串拼键(HashMap思路)

特点:不存JSON,存拼接字符串。

SKU表

CREATE TABLE `product_sku` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `product_id` INT UNSIGNED NOT NULL,
  `spec_key` VARCHAR(100) NOT NULL COMMENT '规格键,color_red|size_xl',
  `spec_value` VARCHAR(200) NOT NULL COMMENT '规格展示,红色|XL',
  `price` DECIMAL(10,2) NOT NULL,
  `stock` INT NOT NULL,
  UNIQUE KEY `uk_product_spec` (`product_id`, `spec_key`)
) ENGINE=InnoDB;

PHP操作

// 生成键
$spec_key = 'color_' . $color . '|size_' . $size;
// 移除无效字符,做哈希后存储,避免字符串太长
$spec_key_hash = md5($spec_key);

优点:查询快(走索引),不需要JSON解析。 缺点:可读性差,需要额外维护规格值映射。


EAV表结构(最灵活,适合超多规格或自定义属性)

适用于商品属性极多且不固定的场景,但查询复杂度极高,不推荐在常规电商使用。

属性定义表

CREATE TABLE `attribute` (
  `attr_id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `attr_name` VARCHAR(50) NOT NULL, -- 颜色、内存、材质等
  `is_sku` TINYINT NOT NULL DEFAULT '0' COMMENT '是否属于SKU维度(影响价格库存),还是普通属性'
);

SKU 属性关系表

CREATE TABLE `sku_attr_value` (
  `id` INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  `sku_id` INT UNSIGNED NOT NULL,
  `attr_id` INT UNSIGNED NOT NULL,
  `value` VARCHAR(100) NOT NULL,
  UNIQUE KEY `uk_sku_attr` (`sku_id`, `attr_id`)
);

关键设计考虑点

  1. JSON vs 字符串:MySQL 5.7+ 支持 JSON 字段,但建议不要spec_info 字段上直接建普通索引或唯一索引,除非使用虚拟列(Generated Column)。

    • 更好的做法:添加一个冗余字段 spec_md5,存储 md5(json_encode($specs)),并在此字段上建立唯一索引,确保同一商品下不会插入重复的SKU组合。
    -- 方案一表的改进版:
    ALTER TABLE `sku` ADD COLUMN `spec_md5` CHAR(32) NOT NULL;
    ALTER TABLE `sku` ADD UNIQUE KEY `uk_spu_spec_md5` (`spu_id`, `spec_md5`);
  2. 库存与价格

    • 不要将库存直接写死为 INT,应预留 DECIMALINT UNSIGNED,同时最好用 乐观锁(版本号)或 悲观锁FOR UPDATE)来防止超卖。
    • 价格用 DECIMAL(10,2),避免浮点误差。
  3. 图片:多规格商品,每个SKU通常有专属图片,可以在SKU表中加入 sku_image 字段;如果所有SKU共用主图,则缺省。

  4. 数据一致性:在后台编辑商品时,如果规格组合变化,需要确保 SKU表规格表 同步更新(通常使用事务 + 全删重插策略,或者差量更新策略)。

  5. 前端交互:通常前端会通过 attributes 数组请求某个SKU,后端通过唯一索引查询并返回价格和库存。


总结推荐

对于绝大多数PHP电商项目(如ThinkPHP、Laravel框架),建议采用“方案一:SPU + SKU + JSON规格 + MD5唯一索引”

这是兼顾灵活性、查询性能与开发效率的最佳平衡点,如果是Spring Boot或更多微服务场景,可以考虑用 MongoDB 存储SKU的嵌套文档,但在PHP传统关系型数据库中(MySQL),上述方案最为稳妥。

抱歉,评论功能暂时关闭!