电商核心概念
InnoShop 中有五个核心数据模型:分类、品牌、规格、选项、属性。理解它们之间的区别和用途,是进行二次开发的基础。
概念对比总结
| 概念 | 用途 | 影响价格 | 影响库存 | 关联方式 |
|---|---|---|---|---|
| 分类 | 组织产品结构 | ❌ | ❌ | 多对多 (product_categories) |
| 品牌 | 标识制造商 | ❌ | ❌ | 一对多 (brand_id) |
| 规格 | 产品变体 SKU | ✅ | ✅ | 一对多 (product_skus) |
| 选项 | 增值服务 | ✅ | ✅ | 多对多 (product_options) |
| 属性 | 产品参数展示 | ❌ | ❌ | 多对多 (product_attributes) |
1. 分类 (Category)
按层级组织产品,便于用户导航和筛选。
电子产品
└── 手机
└── 智能手机特点:树形层级结构(parent_id)、一个产品可属于多个分类、支持 SEO 和多语言。
数据库表:categories(主表)、category_translations(翻译表)、product_categories(关联表)
代码位置:innopacks/common/src/Models/Category.php、Repositories/CategoryRepo.php
$category->children(); // 获取子分类
$category->activeChildren(); // 获取启用的子分类
$category->parent(); // 获取父分类
$category->products(); // 获取分类下的产品2. 品牌 (Brand)
标识产品的制造商或品牌商,便于用户按品牌筛选。
特点:通过 brand_id 外键直接关联产品、支持品牌 Logo、支持首字母筛选。
数据库表:brands(主表,无需翻译表)
代码位置:innopacks/common/src/Models/Brand.php、Repositories/BrandRepo.php
$brand->products();
BrandRepo::getInstance()->autocomplete($keyword);3. 规格 (Specification/Variant)
定义产品的不同版本/SKU,每个规格组合对应一个独立的库存单位。
| 规格组合 | SKU 编码 | 价格 | 库存 |
|---|---|---|---|
| 红色 - 大号 | SKU-001 | ¥99 | 50 |
| 红色 - 中号 | SKU-002 | ¥89 | 30 |
核心概念:
- 规格维度 (
product_variants):如颜色、尺寸 —— 每个产品拥有一个有序的维度列表。 - 规格值 (
product_variant_values):如红色、大号 —— 每个维度拥有一个有序的可选值列表。 - SKU-规格关联 (
product_sku_variant_values):将 SKU 与每个维度的唯一值绑定,数据库层通过UNIQUE(sku_id, variant_id)约束保证每个维度只能选一个值。 - 规格模板 (
variant_templates):可复用的维度 + SKU 矩阵预设,快速为新商品套用常见规格配置。
数据模型(2026-07 起规范化):
product_variants (规格维度)
├── id, product_id, position, is_image
└── product_variant_translations (locale, name)
product_variant_values (每个维度的可选值)
├── id, variant_id, image, position
└── product_variant_value_translations (locale, name)
product_skus (库存单位)
└── product_sku_variant_values (关联中间表)
├── sku_id, variant_id, value_id
└── UNIQUE(sku_id, variant_id)旧的 products.variables JSON 字段已移除。为了向后兼容,$product->variables 现在是一个访问器,通过 LegacyVariablesBuilder 从规范化表中合成旧版数据结构。
合成的 $product->variables 数据示例:
[
{
"name": {"en": "Color", "zh-cn": "颜色"},
"isImage": false,
"values": [
{"name": {"en": "Red", "zh-cn": "红色"}, "image": ""},
{"name": {"en": "Blue", "zh-cn": "蓝色"}, "image": ""}
]
}
]数据库表:product_variants、product_variant_translations、product_variant_values、product_variant_value_translations、product_sku_variant_values、product_skus、variant_templates
代码位置:Models/Product.php、Models/Product/Sku.php、Models/Product/Variant.php、Models/Product/Variant/Value.php、Models/Product/Sku/VariantValue.php、Models/Product/VariantTemplate.php、Repositories/ProductRepo.php、Repositories/Product/VariantRepo.php、Services/LegacyVariablesBuilder.php
// 产品级别
$product->skus(); // 所有 SKU(HasMany)
$product->masterSku(); // 主 SKU(HasOne, is_default=1)
$product->variants(); // 规格维度(HasMany,按 position 排序)
$product->isMultiple(); // 是否多规格商品
$product->variables; // 旧版数据格式(访问器,由 LegacyVariablesBuilder 合成)
$product->variant_dimensions; // 带稳定数据库 ID 的结构化格式
// SKU 级别
$sku->variantValues(); // BelongsToMany 通过 product_sku_variant_values 中间表
$sku->getLocaleLabels(); // [['name'=>'颜色','value'=>'红色'], ...]
$sku->variant_label; // "颜色:红色; 尺寸:L"
$sku->full_name; // "商品名称 (颜色:红色; 尺寸:L)"
// 规格维度级别
$variant->values(); // 当前维度下的所有值(按 position 排序)
$variant->translation->name; // 本地化的维度名称4. 选项 (Option)
购物时可选择的增值服务或附加选项,是产品的补充服务。
| 选项名称 | 可选值 | 价格影响 |
|---|---|---|
| 礼品包装 | 普通包装 / 精美礼盒 | +¥10 |
| 延保服务 | 1年保修 / 2年延保 | +¥99 |
特点:增值服务(非产品变体)、可影响价格、支持必选/可选、多语言 JSON 存储。
数据库表:options、option_values、product_options、product_option_values
代码位置:Models/Option.php、Models/OptionValue.php、Repositories/OptionRepo.php
$product->options(); // 产品的选项
$product->productOptions(); // 选项配置
$option->values(); // 选项的值5. 属性 (Attribute)
描述产品的规格参数和技术指标,用于产品详情页展示和分类页筛选。
| 属性名 | 属性值 |
|---|---|
| 材质 | 纯棉 |
| 重量 | 500g |
特点:产品参数展示、筛选功能、分组管理。筛选逻辑:不同属性组之间是 AND 关系,同一组内多个值是 OR 关系。
筛选 URL 格式:attr=1:10,11|2:20 表示 (属性1=值10 OR 值11) AND (属性2=值20)
数据库表:attributes、attribute_translations、attribute_groups、attribute_values、product_attributes
代码位置:Models/Attribute.php、Models/Attribute/Group.php、Repositories/AttributeRepo.php
$product->productAttributes(); // 产品属性
$product->groupedAttributes(); // 按分组的属性
$attribute->group(); // 属性组
$attribute->values(); // 属性值