# OrderService 架构设计说明 ## 设计理念 OrderService 采用了**统一数据流**的设计理念,无论订单数据来源于购物车还是商品规格,最终都会转换为标准化的 `goods_list` 格式进行处理。这种设计确保了核心业务逻辑的统一性和代码的可维护性。 ## 核心架构 ``` 输入层 数据转换层 核心处理层 输出层 ┌─────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────┐ │购物车ID │ ──► │ 转换为 │ ──► │ │ ──► │ │ │cart_ids │ │ goods_list │ │ 统一计算/ │ │ 订单 │ └─────────┘ └─────────────┘ │ 创建方法 │ │ 结果 │ │ │ │ │ ┌─────────┐ ┌─────────────┐ │ calculate │ └─────────┘ │商品规格 │ ──► │ 验证格式 │ ──► │ Order() │ │goods_list│ │ 直接使用 │ │ │ └─────────┘ └─────────────┘ │ createOrder │ │ () │ └─────────────┘ ``` ## 方法层次结构 ### 1. 统一核心方法 #### calculateOrder() - 统一计算方法 - **作用**: 接收标准化的 `goods_list`,计算订单明细 - **输入**: 标准化商品列表 - **输出**: 订单计算结果 - **特点**: 所有计算逻辑的统一入口 #### createOrder() - 统一创建方法 - **作用**: 接收标准化的 `goods_list`,创建订单 - **输入**: 标准化商品列表 - **输出**: 创建的订单对象 - **特点**: 所有创建逻辑的统一入口 ### 2. 数据转换方法 #### convertCartToGoodsList() - 购物车转换 - **作用**: 将购物车数据转换为标准商品列表格式 - **输入**: 购物车ID数组 - **输出**: 标准化的 `goods_list` ### 3. 对外接口方法 #### calculateOrderByGoods() - 商品规格计算 ```php public static function calculateOrderByGoods($goods_list, $user_id, $area_id, $user_coupon_id) { return self::calculateOrder($goods_list, $user_id, $area_id, $user_coupon_id); } ``` #### calculateOrderByCart() - 购物车计算 ```php public static function calculateOrderByCart($cart_ids, $user_id, $area_id, $user_coupon_id) { $goods_list = self::convertCartToGoodsList($cart_ids, $user_id); return self::calculateOrder($goods_list, $user_id, $area_id, $user_coupon_id); } ``` #### createOrderByGoods() - 商品规格创建 ```php public static function createOrderByGoods($address_id, $user_id, $goods_list, $user_coupon_id, $memo) { return self::createOrder($address_id, $user_id, $goods_list, $user_coupon_id, $memo); } ``` #### createOrderByCart() - 购物车创建 ```php public static function createOrderByCart($address_id, $user_id, $cart_ids, $user_coupon_id, $memo) { $goods_list = self::convertCartToGoodsList($cart_ids, $user_id); return self::createOrder($address_id, $user_id, $goods_list, $user_coupon_id, $memo, $cart_ids); } ``` ## 标准化数据格式 ### goods_list 格式 ```php $goods_list = [ [ 'goods_id' => 1, // 商品ID(必填) 'goods_sku_id' => 5, // 商品规格ID(可选,系统会自动补充默认SKU) 'nums' => 2 // 购买数量(必填) ], [ 'goods_id' => 2, 'goods_sku_id' => 0, // 可以传0或不传,系统会自动查询默认SKU 'nums' => 1 ] ]; ``` ### 重要说明:统一SKU处理机制 在FastAdmin商城系统中,**所有商品(包括单规格商品)都会在SKU表中生成记录**: - **单规格商品**: 会生成一条默认SKU记录,`spec_value_ids`为空,`is_default=1` - **多规格商品**: 会生成多条SKU记录,其中一条标记为`is_default=1` **系统处理逻辑**: 1. 如果传入`goods_sku_id > 0`,直接使用指定的SKU 2. 如果传入`goods_sku_id = 0`或不传,系统自动查询该商品的默认SKU 3. **所有商品最终都通过SKU进行价格、库存、规格计算** 这种设计确保了: - 单规格和多规格商品的处理逻辑完全统一 - 避免了复杂的条件判断 - 提供了更好的扩展性和一致性 ### 数据转换示例 #### 购物车数据 → goods_list ```php // 原始购物车数据 $cartItems = [ ['id' => 1, 'goods_id' => 1, 'goods_sku_id' => 5, 'nums' => 2], ['id' => 2, 'goods_id' => 2, 'goods_sku_id' => 0, 'nums' => 1] ]; // 转换后的 goods_list $goods_list = [ ['goods_id' => 1, 'goods_sku_id' => 5, 'nums' => 2], ['goods_id' => 2, 'goods_sku_id' => 0, 'nums' => 1] ]; ``` ## 设计优势 ### 1. 代码复用性 - **单一核心逻辑**: 订单计算和创建的核心逻辑只有一份 - **避免重复代码**: 不同数据源最终使用相同的处理逻辑 - **易于维护**: 业务规则变更只需修改核心方法 ### 2. 扩展性 - **新增数据源**: 只需实现数据转换方法 - **保持接口兼容**: 现有的对外接口保持不变 - **灵活的组合**: 可以灵活组合不同的数据源和处理方式 ### 3. 一致性 - **统一的验证**: 所有数据都经过相同的验证流程 - **统一的错误处理**: 错误处理逻辑保持一致 - **统一的返回格式**: 不同接口返回相同格式的数据 ### 4. 性能优化 - **批量查询优化**: 使用 IN 查询替代循环查询,大幅提升性能 - **减少数据库连接**: 统一的查询逻辑减少数据库连接次数 - **缓存友好**: 标准化的数据格式便于缓存 - **批量处理**: 可以更好地支持批量操作 #### 性能优化详解 **优化前(循环查询):** ```php foreach ($goods_list as $item) { // 每次循环都要查询数据库 $goods = Goods::where('id', $goods_id)->find(); // N次查询 $sku = Sku::where('id', $sku_id)->find(); // N次查询 $sku_attr = Db::name('shop_goods_sku_spec')... // N次查询 } // 总计: 3N 次数据库查询 ``` **优化后(批量查询):** ```php // 批量查询所有商品 $goodsData = Goods::where('id', 'in', $goods_ids)->select(); // 1次查询 // 批量查询指定的SKU $skuData = Sku::where('id', 'in', $sku_ids)->select(); // 1次查询 // 批量查询没有指定SKU的商品的默认SKU $defaultSkuData = Sku::where('goods_id', 'in', $goods_without_sku) ->where('is_default', 1)->select(); // 1次查询 // 批量查询所有规格属性 $skuAttrData = Db::name('shop_goods_sku_spec')... // 1次查询 foreach ($goods_list as $item) { // 直接从内存中获取数据,无需查询数据库 $goods = $goodsData[$goods_id]; $sku = $skuData[$sku_id]; // 统一使用SKU数据 } // 总计: 最多4次数据库查询(固定) ``` **性能提升:** - 订单包含10个商品时: 30次查询 → 3次查询 (提升90%) - 订单包含100个商品时: 300次查询 → 3次查询 (提升99%) ## 使用场景对比 ### 传统方式(优化前) ```php // 购物车计算 $cartResult = OrderService::calculateOrderByCart($cart_ids, $user_id, $area_id, $coupon_id); // 商品规格计算 $goodsResult = OrderService::calculateOrderByGoods($goods_list, $user_id, $area_id, $coupon_id); // 两套不同的内部实现逻辑 ``` ### 统一方式(优化后) ```php // 购物车模式:先转换,再统一计算 $goods_list = OrderService::convertCartToGoodsList($cart_ids, $user_id); $result = OrderService::calculateOrder($goods_list, $user_id, $area_id, $coupon_id); // 商品规格模式:直接统一计算 $result = OrderService::calculateOrder($goods_list, $user_id, $area_id, $coupon_id); // 同一套核心实现逻辑 ``` ## API控制器层的实现 ### 统一的计算接口 ```php public function calculate() { // 根据类型获取标准化的商品列表 if ($type === 'cart') { $cart_ids = $this->request->post('cart_ids'); $goods_list = OrderService::convertCartToGoodsList($cart_ids, $this->auth->id); } else { $goods_list = $this->request->post('goods_list/a'); } // 统一调用计算方法 $result = OrderService::calculateOrder($goods_list, $this->auth->id, $area_id, $user_coupon_id); } ``` ## 未来扩展可能 ### 1. 新增数据源 - **收藏夹批量下单**: 实现 `convertFavoritesToGoodsList()` - **推荐商品组合**: 实现 `convertRecommendToGoodsList()` - **活动套餐**: 实现 `convertPackageToGoodsList()` ### 2. 新增处理模式 - **预约订单**: 扩展 `calculateOrder()` 支持预约模式 - **分期订单**: 扩展计算逻辑支持分期付款 - **团购订单**: 支持团购价格计算 ### 3. 优化方向 - **异步处理**: 大批量商品的异步计算 - **分布式计算**: 支持微服务架构下的订单计算 - **智能缓存**: 基于商品组合的智能缓存策略 ## 总结 这种统一的架构设计通过**数据标准化 + 核心逻辑统一**的方式,实现了: 1. **简化了代码结构**: 消除了重复的业务逻辑 2. **提高了代码质量**: 统一的验证和错误处理 3. **增强了可维护性**: 核心逻辑修改影响范围明确 4. **提升了扩展性**: 新增功能只需实现数据转换 5. **保证了一致性**: 所有订单操作使用相同的业务规则 这种设计模式体现了软件工程中的**单一职责原则**和**开闭原则**,是一个优秀的架构设计实践。