API接口设计常常遇到的问题其中一个是 管理员和普通用户的使用的数据查询接口是共用还是分开?
- 共用难以理清内部逻辑,往往会在一个接口中添加各种分支判断
- 分开则会影响开发效率,毕竟一个接口现在你需要写两份
用一个例子来说明:
比如查询订单列表 order/list
//管理员可以看到所有用户的订单
//销售员可以看到自己名下的用户的订单
//普通用户只能看到自己的订单
//管理员和销售员要求能看到用户信息、商品价格、商品价格信息和支付信息
//普通用户能看到商品信息和支付信息
代码实现:
首先尝试把所有的查询都集成到一个方法中。
public function allOrderList( int $page = 1, int $pageSize = 10, int $userId = 0, int $adminId = 0, bool $isSuperAdmin = false)
{
//首先判断用户的身份 是普通用户 是销售员,还是超级管理员
//判断用户的查询权限
$orderModel = OrderModel::query();
//如果是管理员显示全部,普通只显示自己,销售员显示所属用户
if ($adminId >= 1) {
if ($isSuperAdmin === false) {
//销售员,查询该销售员下的所有用户
$userIds = [1, 2,3,4,5];
$orderModel->whereIn('user_id', $userIds);
}
} else {
$orderModel->where('user_id', $userId);
}
$res = $orderModel->get();
//如果是管理员和销售员 附加用户信息
if ($adminId >= 1) {
$userInfos = [ 1 => '用户1', 2 => '用户2'];
/** @var OrderModel $item */
foreach ($res as $item) {
$item->setAttribute('userInfo', $userInfos[$item->userId] ?? null );
//如果是管理员和销售员 附加商品价格
}
}
return $res;
}
上面这样做的问题:
- 函数参数太多了,其中夹杂普通用户的查询参数和管理员以及销售员的查询参数
- 函数中的逻辑判断又臭又长,随着需求增加代码逻辑会更长,也会有很多冗余的地方
- 用户逻辑和管理员和销售员逻辑混在在一起不容易维护,当长时间增加不同的逻辑后,开发一个新功能需要对所有的逻辑旁路进行梳理。
- 如果加入查询权限控制、用户权限控制,代码逻辑更为混乱。
个人建议:
- 如果是一套代码完成前后台功能,至少在逻辑层面进行分层,用户是用户,管理员是管理员。使用不同的逻辑空间或者文件夹进行分装。
- 业务逻辑层不要做权限控制,把权限控制放在控制器层(请求入口)去做,业务逻辑层只负责数据的组装。
- 尽量将一大片复杂的业务逻辑拆分成不同的小方法进行复用。
拆分后短期看是比较麻烦的(维护了两个代码,前期好像逻辑没有什么不同),但是长期来看,随着业务的增加,这样势必更容易维护。