简介
本文件面向电商平台开发者,系统化梳理 DouPHP 电商系统的商品主表 dou_product 的表结构设计、字段语义与业务逻辑,覆盖商品基本信息、价格体系、库存管理、状态流转、SEO优化、多语言支持、分类与品牌关联、搜索索引与排序、推荐机制,以及数据导入导出与批量操作的性能优化策略。文档以代码级事实为依据,结合后台与前台模型、服务层与API层的实现,给出可落地的产品数据模型参考。
项目结构
围绕商品主表的数据与能力,涉及以下关键位置:
- 数据库定义:模块备份中的建表脚本,明确 dou_product 与 dou_product_category 等基础表结构及索引。
- 后台模型与服务:负责商品列表、新增、编辑、删除、批量操作、缩略图重建、型号关联等。
- 前台模型:提供商品详情、列表、筛选、排序、推荐、URL与多语言等能力。
- API控制器:对外暴露商品列表查询入口,承接分类、品牌、归档时间窗、排序等参数。
graph TB
A["数据库<br/>dou_product / dou_product_category"] --> B["后台模型<br/>Admin\\Model\\Product\\Product"]
A --> C["前台模型<br/>Front\\Model\\Product\\Product"]
B --> D["后台服务<br/>Admin\\Service\\Product\\ProductService"]
C --> E["API控制器<br/>Api\\Controller\\Product\\ProductController"]
D --> F["附件/图片/缩略图"]
C --> G["品牌/分类/多语言/附件"]
核心组件
- 商品主表 dou_product:承载商品核心属性、价格、库存、状态、SEO、创建者信息、排序等。
- 商品分类表 dou_product_category:用于商品分类树与导航同步。
- 后台模型 Product:声明可写字段、默认排序、过滤条件、多语言清理、型号生成与管理、删除时资源清理。
- 前台模型 Product:声明可翻译字段、列表附加字段、预取器、筛选与排序、推荐、URL与附件访问器。
- 后台服务 ProductService:商品列表组装、新增/更新流程、缩略图重建、型号关联、批量操作。
- API控制器 ProductController:商品列表接口,支持分类、品牌、归档、排序等参数。
架构总览
商品主表在系统中的角色与交互如下:
- 写入路径:后台服务接收表单数据,校验并持久化到 dou_product;处理主图与内容图片;记录管理员日志。
- 读取路径:前台模型通过 AR 查询,配合 with('category')、forUser、prefetchers 进行批量预加载与格式化;API控制器聚合分类树与分页数据返回。
- 索引与排序:基于 slug、operator_type+operator_id 索引;默认排序由配置或固定规则决定。
- 多语言:name/title/content/description 等字段按当前语言覆写;删除时清理 language_value 中 product 模块相关条目。
- 附件与相册:image 为主图文件号;thumb/image_other 通过附件系统生成与获取;相册首图预热提升列表性能。
sequenceDiagram
participant Admin as "后台界面"
participant Service as "后台服务"
participant Model as "后台模型"
participant DB as "数据库"
participant Attach as "附件系统"
Admin->>Service : 提交新增/编辑表单
Service->>Service : 校验与预处理(level_price, content)
Service->>Attach : 存储主图/内容图片(生成缩略图)
Service->>Model : create/update 持久化
Model->>DB : INSERT/UPDATE
Service-->>Admin : 成功/失败响应
详细组件分析
商品主表 dou_product 字段设计
- 自增ID id:主键,唯一标识商品。
- 分类 category_id:外键指向商品分类,用于分类筛选与展示。
- 创建者 operator_type/operator_id:区分管理员与工作端创建者,便于权限边界控制。
- 品牌 brand_id:关联品牌,支持品牌筛选与展示。
- 标题 title:商品名称,支持关键字模糊筛选。
- URL标识 slug:用于友好URL,建立索引加速路由匹配。
- 价格 price:基础售价,单位通常为货币最小单位或元。
- 会员等级价 level_price:序列化数组,表示不同用户等级的折扣价。
- 促销价 promote_price:活动期价格,配合起止时间使用。
- 促销时间 promote_start_at/promote_end_at:限定促销生效区间。
- 库存 stock:可售数量,参与下单扣减与库存预警。
- 自定义字段 defined:序列化数组,扩展商品属性。
- 详情 content:富文本内容,支持远程图片本地化与XSS清洗。
- 缩略图 image:主图文件号,经附件系统生成缩略图。
- 型号 model:用于同型号商品归组,支持自动生成与去重。
- 积分 point:购买赠送积分。
- 销量 sales:累计销售数量,常用于排序与统计。
- SEO关键词 keywords:搜索引擎优化关键词。
- SEO描述 description:搜索引擎优化描述,支持多语言覆写。
- 排序 sort:列表排序权重,默认值与排序策略受配置影响。
- 状态 status:启用/禁用,前台仅显示已启用商品。
- 创建时间 created_at:记录创建时间,支持归档筛选与SEO导出。
价格体系与库存管理
- 价格体系:
- 基础价 price:默认展示与计算基准。
- 促销价 promote_price:在促销时间段内优先展示。
- 会员等级价 level_price:根据用户等级动态计算最终售价,后台服务在保存前序列化。
- 库存管理:
- stock:库存字段,参与列表展示与下单流程;建议结合订单与库存服务做并发扣减与回滚。
- 销量 sales:用于热销排序与统计,建议在下单成功后累加。
flowchart TD
Start(["价格计算入口"]) --> CheckPromo{"是否在促销期?"}
CheckPromo --> |是| UsePromo["使用促销价 promote_price"]
CheckPromo --> |否| UseBase["使用基础价 price"]
UsePromo --> LevelCheck{"是否登录且有等级价?"}
UseBase --> LevelCheck
LevelCheck --> |是| ApplyLevel["应用会员等级价 level_price"]
LevelCheck --> |否| FinalPrice["确定最终售价"]
ApplyLevel --> FinalPrice
FinalPrice --> End(["返回价格"])
状态流转与可见性
- 状态字段 status:1为启用,0为禁用。
- 前台仅展示已启用商品:通过 scopePublished 过滤。
- 后台列表默认排序:当开启手动排序时按 sort ASC, id DESC;否则按 id DESC。
stateDiagram-v2
[*] --> 禁用 : "status=0"
禁用 --> 启用 : "status=1"
启用 --> 禁用 : "下架/禁用"
SEO优化与多语言支持
- SEO字段:keywords、description 用于搜索引擎优化。
- 多语言字段:name/title/content/description 支持按当前语言覆写,通过 translatable 声明。
- 多语言清理:删除商品时清理 language_value 中 module='product' 的相关条目。
classDiagram
class Product {
+string title
+string description
+string keywords
+string content
+translatable name,title,content,description
}
class LanguageValue {
+string module
+int item_id
+string field
+string value
}
Product --> LanguageValue : "删除时清理"
商品分类与品牌关联
- 分类关联:category_id 指向 dou_product_category,支持分类筛选与树形展示。
- 品牌关联:brand_id 指向品牌表,支持品牌筛选与展示。
- 列表预加载:with('category', 'brand') 一次性预加载分类与品牌,减少N+1查询。
erDiagram
DOU_PRODUCT {
int id PK
smallint category_id FK
mediumint brand_id FK
string title
decimal price
decimal promote_price
varchar level_price
smallint stock
text content
varchar image
varchar model
smallint point
mediumint sales
varchar keywords
text description
smallint sort
tinyint status
datetime created_at
}
DOU_PRODUCT_CATEGORY {
smallint id PK
varchar slug
varchar name
varchar icon
varchar keywords
text description
smallint parent_id
tinyint sync_to_nav
tinyint sort
}
BRAND {
int id PK
varchar name
}
DOU_PRODUCT ||--|| DOU_PRODUCT_CATEGORY : "属于"
DOU_PRODUCT ||--|| BRAND : "属于"
搜索索引、排序与推荐
- 搜索索引:
- slug:建立索引,用于URL路由与快速查找。
- operator_type+operator_id:复合索引,用于工作台权限过滤。
- 标题关键字:后台支持按 title LIKE 模糊筛选。
- 排序:
- 前台默认:sort ASC, id DESC。
- 后台默认:根据配置 features.sort 决定是否启用手动排序。
- 推荐:
- 同分类随机推荐:related(catId, number, userId),结合 forUser 注入会员视图字段。
sequenceDiagram
participant Client as "客户端"
participant API as "API控制器"
participant Front as "前台模型"
participant DB as "数据库"
Client->>API : GET /product?id=&brand_id=&by=&sort=&year=&month=
API->>Front : buildProductListData(...)
Front->>DB : 查询 dou_product (published, filter by category/brand/archive)
DB-->>Front : 商品列表
Front-->>API : 商品数据(含分类/品牌/附件/多语言)
API-->>Client : 返回分页结果
商品数据导入导出与批量操作
- 导入:
- 可通过后台服务 insert/update 批量调用,注意 level_price 序列化与 content 远程图片本地化。
- 建议使用事务与分批提交,避免长事务锁表。
- 导出:
- 前台模型声明 export sitemap/llms,支持站点地图与大语言模型内容导出。
- 批量操作:
- 批量删除 del_all:直接 destroy(ids)。
- 批量改分类 category_move:whereIn(id)->update(category_id)。
- 缩略图重建:流式处理 file 表中 product 模块的图片,逐条生成缩略图并输出进度。
flowchart TD
Start(["批量操作入口"]) --> Action{"动作类型"}
Action --> |批量删除| DelAll["destroy(ids)"]
Action --> |批量改分类| MoveCat["whereIn(id).update(category_id)"]
Action --> |缩略图重建| RebuildThumb["流式生成缩略图"]
DelAll --> Log["记录管理员日志"]
MoveCat --> Log
RebuildThumb --> Progress["输出进度JS"]
Log --> End(["完成"])
Progress --> End
依赖关系分析
- 模型依赖:
- 后台模型依赖 ORM Builder、配置、附件、多语言清理工具。
- 前台模型依赖分类、品牌、附件、多语言、URL构建、内容升权等能力。
- 服务依赖:
- 后台服务依赖定价服务、Markdown渲染、附件存储、管理员日志。
- 外部依赖:
- 附件系统:主图与缩略图生成、相册首图获取。
- 数据库:InnoDB引擎,utf8mb4字符集,合理索引与分区策略。
graph LR
P["后台模型 Product"] --> O["ORM Builder"]
P --> C["配置 Config"]
P --> L["多语言清理"]
PS["后台服务 ProductService"] --> PR["定价服务 PricingService"]
PS --> MD["Markdown渲染"]
PS --> ATT["附件系统"]
PF["前台模型 Product"] --> BR["品牌 Brand"]
PF --> CAT["分类 ProductCategory"]
PF --> ATT2["附件系统"]
性能考虑
- 索引优化:
- 对 slug 建立单列索引,提升URL路由匹配速度。
- 对 operator_type+operator_id 建立复合索引,加速工作台权限过滤。
- 建议对 category_id、brand_id、status、created_at 建立常用查询索引,视实际查询模式而定。
- 查询优化:
- 使用 with('category','brand') 预加载分类与品牌,避免N+1。
- 使用 prefetchers 预热 url、language、attachment、gallery_first,降低重复IO。
- 列表分页使用 paginate,限制字段 field 减少传输体积。
- 写入优化:
- 批量操作使用 whereIn 与 update,减少循环开销。
- 缩略图重建采用流式处理,逐条生成并输出进度,避免内存峰值。
- 缓存建议:
- 对热门分类与品牌列表进行缓存。
- 对商品详情页可引入页面级缓存或对象缓存,结合失效策略。
故障排查指南
- 多语言残留:
- 现象:删除商品后 language_value 仍有残留。
- 排查:确认 deleteLanguageValues 是否被调用;检查 purgeRelatedOnDelete 是否覆写正确。
- 缩略图缺失:
- 现象:列表页无缩略图或缩略图尺寸异常。
- 排查:检查 getThumbFileQueryList 与 thumbFlush 是否正确执行;确认磁盘配置与 Image::thumb 参数。
- 价格异常:
- 现象:前端显示价格与预期不符。
- 排查:确认 level_price 序列化是否正确;检查 forUser 是否注入会员视图字段;核对促销时间与 promote_price。
- 排序不符合预期:
- 现象:列表未按 sort 排序。
- 排查:确认 features.sort 配置;检查 scopeApplyDefaultOrder 是否被调用;验证数据库 sort 字段值。
结论
dou_product 作为商品主表,围绕商品基本信息、价格体系、库存管理、状态流转、SEO优化、多语言支持、分类与品牌关联构建了完整的数据模型。通过后台服务与前台模型的协同,实现了高效的列表查询、推荐与导出能力。结合合理的索引与批量操作策略,可在大规模商品场景下保持良好性能。建议在生产环境中持续监控查询热点,按需补充索引与缓存策略,确保系统稳定与可扩展。
附录
- 相关表结构参考:
- 商品主表与分类表建表语句位于模块备份脚本中。
- 关键实现路径参考:
- 后台模型与服务的商品CRUD、批量操作、缩略图重建。
- 前台模型的多语言、附件、推荐与排序。
- API控制器的商品列表接口参数与返回结构。