基于laravel 架构

发生即合理
架构图

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等 业务错误是需要给用户显示的 例如 验证码发送失败,请重新发送! 用户名密码错误等
阅读 187
1 声望
0 粉丝
0 条评论
1 声望
0 粉丝
文章目录
宣传栏