插件分层实战:Service层到底该放业务逻辑还是数据组装?

小助手
小助手 版主圣羽星庭 勋望元宿志愿先锋
社区管理
插件开发 27 浏览 2 回复

最近重构老插件时发现Service层越来越臃肿,仔细分析发现很多同事把两类代码混在一起:

典型问题代码:

class UserService {
    public function getUserWithOrders($uid) {
        // 数据获取
        $user = UserModel::find($uid);
        $orders = OrderModel::where('uid', $uid)->get();
        
        // 业务逻辑
        if($user->vip_level > 3) {
            $orders = $this->applyVipDiscount($orders);
        }
        
        // 数据组装
        return [
            'user' => $user->toArray(),
            'orders' => array_map(function($order){
                return [
                    'id' => $order->id,
                    'price' => $order->price * 0.8 // 折扣计算
                ];
            }, $orders)
        ];
    }
}

推荐拆分方案:

1. Model层:纯数据存取
class UserModel {
    public static function getWithOrders($uid) {
        return self::with('orders')->find($uid);
    }
}
2. Service层:只处理业务规则
class DiscountService {
    public function applyVipPolicy($orders, $vipLevel) {
        return $vipLevel > 3 
            ? array_map(fn($o) => $o->setAttribute('discount', 0.8), $orders)
            : $orders;
    }
}
3. Controller层:组合调用+数据格式化
class UserController {
    public function profile() {
        $data = UserModel::getWithOrders($uid);
        $data['orders'] = (new DiscountService())
            ->applyVipPolicy($data['orders'], $data['user']->vip_level);
        
        return response()->json([
            'user' => UserTransformer::format($data['user']),
            'orders' => OrderTransformer::collection($data['orders'])
        ]);
    }
}

关键原则:Service层应该像调味料,Model层提供原料,Controller负责摆盘。当需要新增折扣类型时,只需修改DiscountService,保持Model稳定。

评论2
回复 · 2
OpenField
OpenField 初级 · #2 ·
支持了~
安然
安然 新手时梦乐园 · #1 ·
同求,期待更新
微信客服 微信客服