架构图
1、Request log 申请报文日志,这里加申请报文的起因是,很多状况下的 BUG 是低频难复现的。原申请报文能很好的排查问题。这一层也能够放在中间件(Middleware)来解决 参考示例:
<?php
namespace App\Http\Middleware;
use App\Http\Controllers\Controller;
use Closure;
class ApiCheck extends Controller
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{$params = $request->input();
$Uri = $request->getRequestUri();
$UriArray = explode('?',$Uri);
$UriArray = explode('/',$UriArray[0]);
$this->dataRecodes('申请报文', $params, $UriArray[3]);
return $next($request);
}
}
class Helper
{
/**
* @Notes: 记录接口日志信息
* @Author: Dong Xiannan
* @Date: 2021/8/5 3:50 下午
* @Description: 形容
* @param $title
* @param $data
* @param string $file
*/
public static function dataRecodes($title, $data, $file = 'log')
{$date = date("Ymd");
if (!is_dir(storage_path('logs/' . $date))) {mkdir(storage_path('logs/' . $date), 0777, TRUE);
}
$content = "================" . $title . '' . date('Y-m-d H:i:s') ."===================\n";
file_put_contents(storage_path('logs/' . $date . '/' . $file . '.log'), $content . var_export($data, 1) . PHP_EOL, 8);
return;
}
2、Middleware 中间件 不做过多阐明 全局中间件、两头组、路由中间件 依据理论场景正当利用
3、Request 层 这里我在中间件和控制器两头加了一层 Request 次要用来做参数校验 示例:
class TestRequest extends BaseRequest
{public function rules()
{
return [
'nickname' => 'required',
'account_name' => 'required',
'role_id' => 'required',
'subject_id' => 'required',
'commission' => 'required',
] + parent::rules();}
public function messages()
{return [] + parent::messages();}
public function attributes()
{
return [
'nickname' => '昵称',
'account_name' => '账号',
'role_id' => '角色 ID',
'subject_id' => '主体 ID',
'commission' => '佣金比例',
] + parent::attributes();}
}
4、Controller(控制器)将简单的业务逻辑从控制器抽离进去放在 Service(服务层)避免控制器臃肿,难懂,不易保护
class UserController extends Controller
{
protected $userRepository;
protected $userService;
public function __construct(UserRepository $userRepository)
{$this->userRepository = $userRepository;}
/**
* Display a listing of the resource.
* @return Renderable
*/
public function index(Request $request, UserService $userService, UserTransformer $userTransformer, UserFormatter $userFormatter)
{$user = $userService->getUserAll();
return response()->json($userFormatter->format($request, $userTransformer->transform($user)));
}
5、Service 层 商业逻辑,不是简略的查问数据,而是特定的工作,例如判断用户是否是会员,设置用户权限等等,这些操作倡议放在 Service,之后 Controller 再调用它
class UserService
{
protected $userRepository;
public function __construct(UserRepository $userRepository)
{$this->userRepository = $userRepository;}
public function getUserAll()
{if(1 == 1){// 会员
return $this->userRepository->getUaerAll();}else{//todo}
}
6、Repository 层,跟 Eloquent/DB 操作相干的,例如增删改查,间接和数据库打交道的根底操作抽出来放在 Repository 中,这样 Model 会变得很洁净
class UserRepository
{
protected $user;
public function __construct(User $user)
{$this->user = $user;}
public function getUaerAll()
{return $this->user->all();
}
7、Transformer,转换器,例如在仓库 repository 中有一个获取所有用户信息的查问操作:
$this->user->all(); 但有些中央咱们不须要用到那么多个字段,我只想有 name 和 email 字段,难道我要去改 all()外面的参数,变成
$this->user->all([‘name’,’email’])? 这样另外的中央又要全副字段,这不就抵触了?这时候 Transformer 就有用了,其实原理是对 $this->user->all() 取得的数据进行筛选后再输入,加了个筛选器。(另外转化器还能够将输入字段和数据字段差别话,起到爱护作用,还能够去除烂尾字段 id、created_at、updated_at 等)
class UserTransformer
{public function transform(Collection $collection)
{$user = $collection->map(function ($user){
return [
'name' => $user->name,
'email' => $user->email
];
});
return $user;
}
8、Formatter 次要用于放弃 API 返回格局的统一
class UserFormatter
{public function format(Request $request, $items)
{
return ['link' => $request->fullUrl(),
'method' => $request->method(),
'code' => Response::HTTP_OK,
'message' => '','items' => $items
];
}
9、return log(返回报文),返回报文和申请报文是成对呈现的 放在日志零碎探讨
10、错误码:错误码须要统一化
- 正确返回 code :0 或者 200
- 零碎谬误 code:-1 或 500 零碎谬误是不须要给用户看的 例如数据库连贯失败等
- 业务谬误 code: 1001、1002、1003 等 业务谬误是须要给用户显示的 例如 验证码发送失败,请从新发送!用户名明码谬误等