插件分层设计的边界难题:何时该把逻辑下沉到Model层
最近重构老插件时遇到个典型问题:订单折扣计算逻辑写在Controller里导致两个问题:1) 单元测试要mock整个HTTP请求 2) 其他Service无法复用。分享下我们团队讨论出的分层原则:
Model层该做的三件事: 1. 基础字段的getter/setter(带类型转换) 2. 简单派生属性(如订单总价=单价*数量) 3. 当前对象的基础CRUD操作
Service层专属的三种情况: 1. 跨Model的业务流程(如创建订单+扣库存+发通知) 2. 需要依赖外部服务的操作(如调用支付网关) 3. 复杂计算逻辑(含if/switch分支的都应放在这)
典型误用案例:把优惠券核销逻辑写在OrderModel里,导致: ```php // ❌ 错误示范 class OrderModel { public function applyCoupon() { // 调用第三方券码服务 $client = new CouponClient(); $valid = $client->verify(...); // 修改订单金额 $this->discount = ...; } } ```
正确拆解姿势: ```php // ✅ 清晰分层 class CouponService { public function applyToOrder(OrderModel $order) { $this->client->verify(...); $order->setDiscount(...); // Model只做基础赋值 } } // Controller只剩三行 $order = OrderModel::find($id); $this->couponService->applyToOrder($order); return $order->save(); ```
关键判断标准:当某个方法需要引入新依赖(如日志服务、HTTP客户端)时,就该考虑提到Service层了。你们团队的分层规范是怎样的?欢迎交流实战中的边界case~

