Laravel 开发Api规范
一,修改时区
配置 config/app.php 文件
// 时区修改,感觉两者皆可,自己根据实际情况定义
'timezone' => 'PRC', // 大陆时间
二,设置 Accept 头中间件
accept头即为客户端请求头,做成中间件来使用。Accept 决定了响应返回的格式,设置为 application/json, 遇到的所有报错 Laravel 会默认处理为 JSON 格式。
- 生成中间件
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);}
}
- 添加到全局中间件
修改文件 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 文件
异常分为两种,一种是要给前端返回展示的,比如表单验证,一种是不需要给前端展示的,比如服务器内部错误。
- 在 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);}
}
- 自定义返回异常
修改 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']);});
});
相关文章:
Laravel 开发Api规范
一,修改时区 配置 config/app.php 文件 // 时区修改,感觉两者皆可,自己根据实际情况定义 timezone > PRC, // 大陆时间二,设置 Accept 头中间件 accept头即为客户端请求头,做成中间件来使用。Accept 决定了响应返…...
蓝色wordpress外贸建站模板
蓝色wordpress外贸建站模板 https://www.mymoban.com/wordpress/7.html...
windos环境,使用docker容器运行项目的,新增外部访问地址配置
对于运行在 Docker 容器中的项目,你需要在容器内部编辑 resolv.conf 文件。以下是一种常见的方法: 进入正在运行的 Docker 容器:docker exec -it [container_id] bash其中 [container_id] 是你正在运行的 Docker 容器的 ID。 在容器内部使…...
设计模式:生活中的组合模式
想象一下,你正在组织一个大型的家庭聚会。在这个聚会中,你需要准备各种菜肴,每个菜肴又包含不同的食材。你的目标是能够以统一的方式处理整个聚会的准备工作,不论是处理单个食材还是一整道菜肴。 在这个场景中,我们可…...
WPF OnStartup
在Windows Presentation Foundation (WPF)框架中,OnStartup 是 System.Windows.Application 类的一个受保护的虚方法,它是应用程序启动过程中的一个重要环节。当一个 WPF 应用程序启动时,其入口点通常是 App.xaml 文件和对应的后台代码文件 A…...
docker-相关
打镜像 1、编写dockfile文件,请自行百度 2、docker build -t 镜像名称:版本号 dockerFile路径 3、docker save -o 镜像压缩包名称.tar 镜像名称:镜像版本号 部署镜像 1、将镜像tar包放到部署机器上 2、加载镜像:docker load -i 镜像tar包路径 3、dock…...
二十、Rust AOP 切面增强
用过 java spring 的同学,应该会对 AspectJ 的 前置、后置、环绕 增强 念念不忘,巧了 rust 也有类似能力,稍显不同的是,为了向 “零成本抽象” 靠齐,Rust 的 “增强” 是在编译期 完成的。 编译期生成,则离…...
掌握Go语言:Go语言精细错误,清晰、高效的错误处理实践(32)
错误处理是任何编程语言中都至关重要的一部分,Go 语言提供了一套简单而强大的错误处理机制,使得处理错误变得高效而清晰。 Go 错误类型 在 Go 中,错误是一个普通的接口类型,即 error 接口,其定义如下: t…...
Spring与Web环境的集成
1. ApplicationContext应用上下文获取方式 应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件) 方式获取的,但是每次从容器中获得Bean时都要编写new ClasspathXmlApplicationContext(spring配置文件) ,这样的弊端是配置文件加载多…...
二叉树的遍历——bfs广度优先搜索
1、BinNode类的创建 (1)代码总览 ##(2)测试示例 2、二叉树的遍历 (1)图示 (2)代码总览 (3)测试示例...
飞鸟写作可靠吗 #职场发展#经验分享#经验分享
飞鸟写作是一个非常便捷的论文写作工具,不仅可以帮助用户高效地完成论文写作,还可以提供查重降重的功能,帮助用户确保论文的原创性。那么,飞鸟写作到底可靠吗?答案是肯定的。 首先,飞鸟写作提供的查重降重功…...
Java 实现自定义注解
一、interface 关键字 我们想定义一个自己的注解 需要使用 interface 关键字来定义。 如定义一个叫 MyAnnotation 的注解: public interface MyAnnotation { } 二、元注解 光加上 interface 关键字 还不够,我们还需要了解5大元注解 RetentionTargetDo…...
代码随想录Day48
Day 48 动态规划part09 今日任务 198.打家劫舍213.打家劫舍II337.打家劫舍III 代码实现 基础打家劫舍 class Solution {public static int rob(int[] nums) {if (nums null || nums.length 0) return 0;if (nums.length 1) return nums[0];int[] dp new int[nums.leng…...
Web 后台项目,权限如何定义、设置、使用:菜单权限、按钮权限 ts element-ui-Plus
Web 后台项目,权限如何定义、设置、使用:菜单权限、按钮权限 ts element-ui-Plus 做一个后台管理项目,里面需要用到权限管理。这里说一下权限定义的大概,代码不多,主要讲原理和如何实现它。 一、权限管理的原理 权限…...
ADB 操作命令及其详细用法
adb devices 用途:列出连接到计算机的所有 Android 设备。详解:执行该命令后,ADB 将扫描连接到计算机的所有 Android 设备,并列出它们的序列号。 adb connect <device> 用途:连接到指定 IP 地址的 Android 设备。…...
类的函数成员(三):拷贝构造函数
一.什么是拷贝构造函数? 1.1 概念 同一个类的对象在内存中有完全相同的结构,如果作为一个整体进行复制或称拷贝是完全可行的。这个拷贝过程只需要拷贝数据成员,而函数成员是共用的(只有一份拷贝)。 在建立对象…...
C#操作MySQL从入门到精通(8)——对查询数据进行高级过滤
前言 我们在查询数据库中数据的时候,有时候需要剔除一些我们不想要的数据,这时候就需要对数据进行过滤,比如学生信息中,我只需要年龄等于18的,同时又要家乡地址是安徽的,类似这种操作专栏第7篇的C#操作MySQL从入门到精通(7)——对查询数据进行简单过滤简单过滤方法就无法…...
Centos 7 安装通过yum安装google浏览器
在CentOS 7上使用yum安装Google Chrome浏览器稍微复杂一些,因为Chrome并不直接包含在默认的Yum仓库中。按照以下步骤来操作: 1、添加Google Chrome仓库 首先,您需要手动添加Google Chrome的Yum仓库。打开终端,并使用文本编辑器&a…...
题目:学习使用按位与 。
题目:学习使用按位与 & 。 There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheated shoul…...
逐步分解,一文教会你如何用 jenkins+docker 实现主从模式
jenkins 主从模式想必大家都不陌生,大家在学习过程中为了学习方便都在自己本地搭建了 jenkins 环境,然后通过 javaweb 方式实现,对于 docker 下实现主从模式大家好像兴趣挺大。 今天就通过这篇文章给大家讲讲怎么玩,希望对大家有…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
