Laravel 开发Api规范

一,修改时区

配置 config/app.php 文件

// 时区修改,感觉两者皆可,自己根据实际情况定义
'timezone' => 'PRC', // 大陆时间

二,设置 Accept 头中间件

accept头即为客户端请求头,做成中间件来使用。Accept 决定了响应返回的格式,设置为 application/json, 遇到的所有报错 Laravel 会默认处理为 JSON 格式。

  1. 生成中间件
php artisan make:middleware AcceptHeader
<?php
namespace App\Http\Middleware;
use Closure;
class AcceptHeader
{public function handle($request, Closure $next){$request->headers->set('Accept', 'application/json');return $next($request);}
}
  1. 添加到全局中间件
    修改文件 app/http/Kernel.php
protected $middlewareGroups = ['web' => [...],'api' => [\App\Http\Middleware\AcceptHeader::class,...],
];

二,统一封装响应码

Enum 枚举,新建app/Enums/ResponseEnum.php

<?phpnamespace App\Enums;class ResponseEnum
{// sevming/laravel-response 默认以 '|' 作为分割错误码与错误信息的字符串public const INVALID_REQUEST = '无效请求|21001';// 001 ~ 099 表示系统状态;100 ~ 199 表示授权业务;200 ~ 299 表示用户业务/*-------------------------------------------------------------------------------------------*/// 100开头的表示 信息提示,这类状态表示临时的响应// 100 - 继续// 101 - 切换协议/*-------------------------------------------------------------------------------------------*/// 200表示服务器成功地接受了客户端请求const HTTP_OK = [200001, '操作成功'];const HTTP_ERROR = [200002, '操作失败'];const HTTP_ACTION_COUNT_ERROR = [200302, '操作频繁'];const USER_SERVICE_LOGIN_SUCCESS = [200200, '登录成功'];const USER_SERVICE_LOGIN_ERROR = [200201, '登录失败'];const USER_SERVICE_LOGOUT_SUCCESS = [200202, '退出登录成功'];const USER_SERVICE_LOGOUT_ERROR = [200203, '退出登录失败'];const USER_SERVICE_REGISTER_SUCCESS = [200104, '注册成功'];const USER_SERVICE_REGISTER_ERROR = [200105, '注册失败'];const USER_ACCOUNT_REGISTERED = [23001, '账号已注册'];/*-------------------------------------------------------------------------------------------*/// 300开头的表示服务器重定向,指向的别的地方,客户端浏览器必须采取更多操作来实现请求// 302 - 对象已移动。// 304 - 未修改。// 307 - 临时重定向。/*-------------------------------------------------------------------------------------------*/// 400开头的表示客户端错误请求错误,请求不到数据,或者找不到等等// 400 - 错误的请求const CLIENT_NOT_FOUND_HTTP_ERROR = [400001, '请求失败'];const CLIENT_PARAMETER_ERROR = [400200, '参数错误'];const CLIENT_CREATED_ERROR = [400201, '数据已存在'];const CLIENT_DELETED_ERROR = [400202, '数据不存在'];// 401 - 访问被拒绝const CLIENT_HTTP_UNAUTHORIZED = [401001, '授权失败,请先登录'];const CLIENT_HTTP_UNAUTHORIZED_EXPIRED = [401200, '账号信息已过期,请重新登录'];const CLIENT_HTTP_UNAUTHORIZED_BLACKLISTED = [401201, '账号在其他设备登录,请重新登录'];// 403 - 禁止访问// 404 - 没有找到文件或目录const CLIENT_NOT_FOUND_ERROR = [404001, '没有找到该页面'];// 405 - 用来访问本页面的 HTTP 谓词不被允许(方法不被允许)const CLIENT_METHOD_HTTP_TYPE_ERROR = [405001, 'HTTP请求类型错误'];// 406 - 客户端浏览器不接受所请求页面的 MIME 类型// 407 - 要求进行代理身份验证// 412 - 前提条件失败// 413 – 请求实体太大// 414 - 请求 URI 太长// 415 – 不支持的媒体类型// 416 – 所请求的范围无法满足// 417 – 执行失败// 423 – 锁定的错误/*-------------------------------------------------------------------------------------------*/// 500开头的表示服务器错误,服务器因为代码,或者什么原因终止运行// 服务端操作错误码:500 ~ 599 开头,后拼接 3 位// 500 - 内部服务器错误const SYSTEM_ERROR = [500001, '服务器错误'];const SYSTEM_UNAVAILABLE = [500002, '服务器正在维护,暂不可用'];const SYSTEM_CACHE_CONFIG_ERROR = [500003, '缓存配置错误'];const SYSTEM_CACHE_MISSED_ERROR = [500004, '缓存未命中'];const SYSTEM_CONFIG_ERROR = [500005, '系统配置错误'];// 业务操作错误码(外部服务或内部服务调用)const SERVICE_REGISTER_ERROR = [500101, '注册失败'];const SERVICE_LOGIN_ERROR = [500102, '登录失败'];const SERVICE_LOGIN_ACCOUNT_ERROR = [500103, '账号或密码错误'];const SERVICE_USER_INTEGRAL_ERROR = [500200, '积分不足'];//501 - 页眉值指定了未实现的配置//502 - Web 服务器用作网关或代理服务器时收到了无效响应//503 - 服务不可用。这个错误代码为 IIS 6.0 所专用//504 - 网关超时//505 - HTTP 版本不受支持/*-------------------------------------------------------------------------------------------*/
}

三,封装 API 返回的统一消息(ApiResponse)

在 app/Helpers 目录下创建 ApiResponse.php 文件

<?phpnamespace App\Helpers;use App\Enum\ResponseEnum;
use App\Exceptions\BaseException;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;trait ApiResponse
{/*** 成功* @param null $data* @param array $codeResponse* @return JsonResponse*/public function success($data = null, $codeResponse = ResponseEnum::HTTP_OK): JsonResponse{return $this->jsonResponse('success', $codeResponse, $data);}/*** 失败* @param array $codeResponse* @param null $data* @param null $error* @return JsonResponse*/public function fail($codeResponse = ResponseEnum::HTTP_ERROR, $data = null): JsonResponse{return $this->jsonResponse('fail', $codeResponse, $data);}/*** json响应* @param $status* @param $codeResponse* @param $data* @param $error* @return JsonResponse*/private function jsonResponse($status, $codeResponse, $data): JsonResponse{list($code, $message) = $codeResponse;return response()->json(['status' => $status,'code' => $code,'message' => $message,'data' => $data ?? null,]);}/*** 成功分页返回* @param $page* @return JsonResponse*/protected function successPaginate($page): JsonResponse{return $this->success($this->paginate($page));}private function paginate($page){if ($page instanceof LengthAwarePaginator) {return ['total' => $page->total(),'page' => $page->currentPage(),'limit' => $page->perPage(),'pages' => $page->lastPage(),'list' => $page->items()];}if ($page instanceof Collection) {$page = $page->toArray();}if (!is_array($page)) {return $page;}$total = count($page);return ['total' => $total, //数据总数'page' => 1, // 当前页码'limit' => $total, // 每页的数据条数'pages' => 1, // 最后一页的页码'list' => $page // 数据];}/*** 业务异常返回* @param array $codeResponse* @param string $info* @throws BaseException*/public function throwBaseException(array $codeResponse = ResponseEnum::HTTP_ERROR, string $info = ''){throw new BaseException($codeResponse, $info);}
}

四,创建项目异常捕获 Exception 文件

异常分为两种,一种是要给前端返回展示的,比如表单验证,一种是不需要给前端展示的,比如服务器内部错误。

  1. 在 app/Exceptions 目录下创建 BaseException.php 文件用于服务器内部异常的抛出
<?phpnamespace App\Exceptions;use Exception;
class BaseException extends Exception
{/*** 基础异常构造函数* @param array $codeResponse 状态码* @param string $info 自定义返回信息,不为空时会替换掉codeResponse 里面的message文字信息*/public function __construct(array $codeResponse, $info = ''){[$code, $message] = $codeResponse;parent::__construct($info ?: $message, $code);}
}
  1. 自定义返回异常
    修改 app/Exceptions 目录下的 Handler.php 文件
<?phpnamespace App\Exceptions;use App\Enum\ResponseEnum;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Validation\ValidationException;
use Throwable;
use App\Helpers\ApiResponse;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;class Handler extends ExceptionHandler
{use ApiResponse;/*** A list of exception types with their corresponding custom log levels.** @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>*/protected $levels = [//];/*** A list of the exception types that are not reported.** @var array<int, class-string<\Throwable>>*/protected $dontReport = [//];/*** A list of the inputs that are never flashed to the session on validation exceptions.** @var array<int, string>*/protected $dontFlash = ['current_password','password','password_confirmation',];/*** Register the exception handling callbacks for the application.** @return void*/public function register(){$this->reportable(function (Throwable $e) {//});}public function render($request, Throwable $exception){   //判断只接管api部分的异常if ($request->is('api/*')) {// 请求类型错误异常抛出if ($exception instanceof MethodNotAllowedHttpException) {$this->throwBaseException(ResponseEnum::CLIENT_METHOD_HTTP_TYPE_ERROR);} // 参数校验错误异常抛出elseif ($exception instanceof ValidationException) {$this->throwBaseException(ResponseEnum::CLIENT_PARAMETER_ERROR, $exception->getMessage());} // 路由不存在异常抛出elseif ($exception instanceof NotFoundHttpException) {$this->throwBaseException(ResponseEnum::CLIENT_NOT_FOUND_ERROR);} // 自定义错误异常抛出elseif ($exception instanceof BaseException) {return response()->json(['status' => 'fail','code' => $exception->getCode(),'message' => $exception->getMessage(),'data' => null,]);//系统异常} else {//生产模式if (config('app.debug')) {return response()->json(['status' => 'fail','code' => 500,'message' => "服务器内部错误!",'data' => null,]);} else {return response()->json(['status' => 'fail','code' => 500,'message' => $exception->getMessage(),'data' => null]);}}}return parent::render($request, $exception);}
}

五,使用

路由定义如下

Route::prefix('v1')->name('api.v1.')->group(function() {Route::get('version', function() {return 'this is version v1';})->name('version');//限速,每分钟只能请求10次Route::get('test', [TestController::class,'test'])->middleware(['throttle:10,1']);Route::post('login', [TestController::class,'login']);Route::post('register', [TestController::class,'register']);Route::group(['middleware' => 'auth.jwt'], function () {Route::get('user', [TestController::class,'user']);Route::get('logout', [TestController::class,'logout']);Route::get('refresh', [TestController::class,'refresh']);});
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/797771.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

gma 教程:计算标准化降水指数(SPI)

安装 gma&#xff1a;pip install gma &#xff08;依赖的 gdal 需自行安装&#xff09; 本文基于&#xff1a;gma 2.0.8&#xff0c;Python 3.10 本文用到数据请从 gma 网站获取&#xff1a;https://gma.luosgeo.com/UserGuide/climet/Index/SPI.html 。 SPEI 函数简介 gma.c…

c#编程基础学习之方法

目录 C#方法方法参数默认参数值多个参数返回值命名参数 方法重载 C#方法 实例 在程序类内创建一个方法&#xff1a; class Program {static void MyMethod() //static 静态意味着方法属于程序类&#xff0c;而不是程序类的对象。void 表示此方法没有返回值。MyMethod() 是方法…

比较720组结构数列的收敛过程

在行&#xff0c;列可自由变换的平面上3点结构只有6个 这次计算由这6个结构排列组合&#xff0c;构成的所有720个不重复数列的递推收敛过程。 结果表明&#xff0c;所有的数列都可以在有限步内收敛。 有461个数列在3-4-3的递推过程中是天然稳定的&#xff0c;收敛结果就是本身…

上海计算机学会 2024年3月月赛 丙组T1 最近的数字(数学)

第一题&#xff1a;T1最近的数字 标签&#xff1a;数学题意&#xff1a;给定两个正整数 n n n与 d d d&#xff0c;请找到所有最接近 n n n且是 d d d的倍数的整数。如果有多个数字满足要求&#xff0c;从小到大输出。数据范围&#xff1a; 1 ≤ n , d ≤ 1 , 000 , 000 , 000…

STM32学习和实践笔记(4):分析和理解GPIO_InitTypeDef GPIO_InitStructure (c)

第二个成员变量是GPIOSpeed_TypeDef GPIO_Speed&#xff1b;也与int a一样同理。 GPIOSpeed_TypeDef是一个枚举类型&#xff0c;其定义如下&#xff1a; typedef enum { GPIO_Speed_10MHz 1, GPIO_Speed_2MHz, GPIO_Speed_50MHz }GPIOSpeed_TypeDef; #define IS_GPI…

.NET Standard、.NET Framework 、.NET Core三者的关系与区别?

.NET Standard、.NET Framework 和 .NET Core 是 .NET 平台生态中的三个关键概念&#xff0c;它们之间存在明确的关系和显著的区别。下面分别阐述它们各自的角色以及相互间的关系&#xff1a; .NET Standard 角色&#xff1a; .NET Standard 是一套正式的 API 规范&#xff0c…

项目经理常用的工具模型有哪些?

项目经理常用的工具模型包括但不限于以下几种&#xff1a; 甘特图&#xff1a;这是一种将大型项目划分为几个阶段&#xff0c;并展示项目进度的工具。在甘特图中&#xff0c;可以清晰地看到每个任务的开始和结束时间&#xff0c;以及任务之间的依赖关系。 工作分解结构&#…

Leetcode刷题-哈希表详细总结(Java)

哈希表 当我们想使⽤哈希法来解决问题的时候&#xff0c;我们⼀般会选择如下三种数据结构。 数组set &#xff08;集合&#xff09;map&#xff08;映射&#xff09; 当我们遇到了要快速判断⼀个元素是否出现集合⾥的时候&#xff0c;就要考虑哈希法。如果在做⾯试题⽬的时候…

解决npm install报错npm ERR Unsupported URL Type “npm:“: npm:vue-loader@^16.1.0 问题

node版本以及npm版本太旧会造成这个问题 1.下载安装nvm 网址&#xff1a;Releases coreybutler/nvm-windows GitHub 2.安装 后使用nvm命令安装切换node版本 安装node版本&#xff1a; nvm install 12.22.12 等待安装完成&#xff0c;使用命令切换版本 nvm use 12.22.1…

Samba 总是需要输入网络凭证

输入网络凭证&#xff1a; 用户名是 cat /etc/samba/smb.conf&#xff0c;查看 valid users mxw 为用户名。而不是其他账号名或者用户名&#xff0c;更不是登录计算机时的计算机名&#xff1b; 密码是 需要记住安装samba服务器时&#xff0c;自己设置的password&#xff1…

LED发光模组的故障及解决方法

LED发光模组在应用过程中可能会出现各种故障&#xff0c;正确诊断并采取相应的解决方法至关重要&#xff0c;以下是一些常见故障现象及其解决方法的总结&#xff1a; 一、现象&#xff1a;所有的LED闪烁 问题&#xff1a;接触不良 解决方法&#xff1a;检查并重新固定松动处&am…

单片机为什么还在用C语言编程?

单片机产品的成本是非常敏感的。因此对于单片机开发来说&#xff0c;最重要的是在极其有限的ROM和RAM中实现最多产品的功能。或者反过来说&#xff0c;实现相同的产品功能&#xff0c;所需要的ROM和RAM越小越好&#xff0c;在开始前我有一些资料&#xff0c;是我根据网友给的问…

linux网络预备

网络预备 网络协议初识 协议分层 打电话例子 在这个例子中, 我们的协议只有两层; 但是实际的网络通信会更加复杂, 需要分更多的层次。 分层最大的好处在于 “封装” 。 OSI七层模型 OSI&#xff08;Open System Interconnection&#xff0c;开放系统互连&#xff09;七层网…

Datacom HCIP笔记-路由策略与路由控制 之二

路由策略和策略的区别&#xff1f; 路由策略&#xff1a; 操作的对象是路由表条目&#xff0c; 实现路由过滤&#xff0c;从而实现访问控制&#xff0c;引入时过滤&#xff0c;发送和接收路由时过滤。 通过配置cost&#xff0c;来实现路径的控制。 策略路由&#xff1a; 对…

【Vue3源码学习】— CH2.8 Vue 3 响应式系统小结

Vue 3 响应式系统小结 1.核心概念1.1 Proxy和Reflect1.2 响应式API1.3 依赖收集与更新触发1.4 触发更新&#xff08;Triggering Updates&#xff09;&#xff1a;1.5 副作用函数&#xff08;Effect&#xff09;1.6 计算属性和观察者1.7 EffectScope1.8 性能优化&#xff1a; 2.…

GPT-5将在6月发布前进行「红队进攻测试」

“GPT-5将在6月发布”的消息刷屏了AI朋友圈。这则消息之所以被无数人相信并转发&#xff0c;是因为已经有不少技术人员在社交平台上晒出了「红队进攻测试」邀请。 基于 GPT系列庞大的用户体量和影响力&#xff0c;OpenAI 将更加重视GPT-5 的安全性&#xff0c;作为GPT-5上市前的…

【编译原理】手工打造语法分析器

重点&#xff1a; 语法分析的原理递归下降算法&#xff08;Recursive Descent Parsing&#xff09;上下文无关文法&#xff08;Context-free Grammar&#xff0c;CFG&#xff09; 关键点&#xff1a; 左递归问题深度遍历求值 - 后续遍历 上一篇「词法分析器」将字符串拆分为…

AudioLDM2全文翻译

AUDIOLDM 2: LEARNING HOLISTIC AUDIO GENERAT I O N W I T H SELF-SUPERVISED PRETRAINING 由于原本在notion上写的&#xff0c;文章中的文字链接大部分是我查询的一些资料&#xff0c;做的内部引用&#xff0c;所以无法展示。文章图片部分请参考原论文&#xff0c;相关工作部…

水经微图网页版309项功能清单

让每一个人都有自己的地图&#xff01; 水经微图&#xff08;简称“微图”&#xff09;网页版&#xff0c;是越来越受到大家的亲睐了&#xff01; 就后台统计数据来看&#xff0c;日均IP数据在稳步增长&#xff0c;老访客的占比最高达35%以上。 在上上周&#xff0c;还分别有…

PMP考试费太贵,能不能自学?

最近6月PMP考试报名工作正在如火如荼的进行&#xff0c;可能大家对于考试费用已经有了基本了解&#xff0c;今天给大家分享一下PMP证书考下来需要花费多少&#xff1f;能不能自己学习&#xff1f; PMP是什么&#xff1f; PMP项目管理专业人士资格认证&#xff0c;由项目管理协…