当前位置: 首页 > news >正文

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']);});
});

相关文章:

Laravel 开发Api规范

一&#xff0c;修改时区 配置 config/app.php 文件 // 时区修改&#xff0c;感觉两者皆可&#xff0c;自己根据实际情况定义 timezone > PRC, // 大陆时间二&#xff0c;设置 Accept 头中间件 accept头即为客户端请求头&#xff0c;做成中间件来使用。Accept 决定了响应返…...

蓝色wordpress外贸建站模板

蓝色wordpress外贸建站模板 https://www.mymoban.com/wordpress/7.html...

windos环境,使用docker容器运行项目的,新增外部访问地址配置

对于运行在 Docker 容器中的项目&#xff0c;你需要在容器内部编辑 resolv.conf 文件。以下是一种常见的方法&#xff1a; 进入正在运行的 Docker 容器&#xff1a;docker exec -it [container_id] bash其中 [container_id] 是你正在运行的 Docker 容器的 ID。 在容器内部使…...

设计模式:生活中的组合模式

想象一下&#xff0c;你正在组织一个大型的家庭聚会。在这个聚会中&#xff0c;你需要准备各种菜肴&#xff0c;每个菜肴又包含不同的食材。你的目标是能够以统一的方式处理整个聚会的准备工作&#xff0c;不论是处理单个食材还是一整道菜肴。 在这个场景中&#xff0c;我们可…...

WPF OnStartup

在Windows Presentation Foundation (WPF)框架中&#xff0c;OnStartup 是 System.Windows.Application 类的一个受保护的虚方法&#xff0c;它是应用程序启动过程中的一个重要环节。当一个 WPF 应用程序启动时&#xff0c;其入口点通常是 App.xaml 文件和对应的后台代码文件 A…...

docker-相关

打镜像 1、编写dockfile文件&#xff0c;请自行百度 2、docker build -t 镜像名称:版本号 dockerFile路径 3、docker save -o 镜像压缩包名称.tar 镜像名称:镜像版本号 部署镜像 1、将镜像tar包放到部署机器上 2、加载镜像&#xff1a;docker load -i 镜像tar包路径 3、dock…...

二十、Rust AOP 切面增强

用过 java spring 的同学&#xff0c;应该会对 AspectJ 的 前置、后置、环绕 增强 念念不忘&#xff0c;巧了 rust 也有类似能力&#xff0c;稍显不同的是&#xff0c;为了向 “零成本抽象” 靠齐&#xff0c;Rust 的 “增强” 是在编译期 完成的。 编译期生成&#xff0c;则离…...

掌握Go语言:Go语言精细错误,清晰、高效的错误处理实践(32)

错误处理是任何编程语言中都至关重要的一部分&#xff0c;Go 语言提供了一套简单而强大的错误处理机制&#xff0c;使得处理错误变得高效而清晰。 Go 错误类型 在 Go 中&#xff0c;错误是一个普通的接口类型&#xff0c;即 error 接口&#xff0c;其定义如下&#xff1a; t…...

Spring与Web环境的集成

1. ApplicationContext应用上下文获取方式 应用上下文对象是通过new ClasspathXmlApplicationContext(spring配置文件) 方式获取的&#xff0c;但是每次从容器中获得Bean时都要编写new ClasspathXmlApplicationContext(spring配置文件) &#xff0c;这样的弊端是配置文件加载多…...

二叉树的遍历——bfs广度优先搜索

1、BinNode类的创建 &#xff08;1&#xff09;代码总览 ##&#xff08;2&#xff09;测试示例 2、二叉树的遍历 &#xff08;1&#xff09;图示 &#xff08;2&#xff09;代码总览 &#xff08;3&#xff09;测试示例...

飞鸟写作可靠吗 #职场发展#经验分享#经验分享

飞鸟写作是一个非常便捷的论文写作工具&#xff0c;不仅可以帮助用户高效地完成论文写作&#xff0c;还可以提供查重降重的功能&#xff0c;帮助用户确保论文的原创性。那么&#xff0c;飞鸟写作到底可靠吗&#xff1f;答案是肯定的。 首先&#xff0c;飞鸟写作提供的查重降重功…...

Java 实现自定义注解

一、interface 关键字 我们想定义一个自己的注解 需要使用 interface 关键字来定义。 如定义一个叫 MyAnnotation 的注解&#xff1a; public interface MyAnnotation { } 二、元注解 光加上 interface 关键字 还不够&#xff0c;我们还需要了解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 后台项目&#xff0c;权限如何定义、设置、使用&#xff1a;菜单权限、按钮权限 ts element-ui-Plus 做一个后台管理项目&#xff0c;里面需要用到权限管理。这里说一下权限定义的大概&#xff0c;代码不多&#xff0c;主要讲原理和如何实现它。 一、权限管理的原理 权限…...

ADB 操作命令及其详细用法

adb devices 用途&#xff1a;列出连接到计算机的所有 Android 设备。详解&#xff1a;执行该命令后&#xff0c;ADB 将扫描连接到计算机的所有 Android 设备&#xff0c;并列出它们的序列号。 adb connect <device> 用途&#xff1a;连接到指定 IP 地址的 Android 设备。…...

类的函数成员(三):拷贝构造函数

一.什么是拷贝构造函数&#xff1f; 1.1 概念 同一个类的对象在内存中有完全相同的结构&#xff0c;如果作为一个整体进行复制或称拷贝是完全可行的。这个拷贝过程只需要拷贝数据成员&#xff0c;而函数成员是共用的&#xff08;只有一份拷贝&#xff09;。 在建立对象…...

C#操作MySQL从入门到精通(8)——对查询数据进行高级过滤

前言 我们在查询数据库中数据的时候,有时候需要剔除一些我们不想要的数据,这时候就需要对数据进行过滤,比如学生信息中,我只需要年龄等于18的,同时又要家乡地址是安徽的,类似这种操作专栏第7篇的C#操作MySQL从入门到精通(7)——对查询数据进行简单过滤简单过滤方法就无法…...

Centos 7 安装通过yum安装google浏览器

在CentOS 7上使用yum安装Google Chrome浏览器稍微复杂一些&#xff0c;因为Chrome并不直接包含在默认的Yum仓库中。按照以下步骤来操作&#xff1a; 1、添加Google Chrome仓库 首先&#xff0c;您需要手动添加Google Chrome的Yum仓库。打开终端&#xff0c;并使用文本编辑器&a…...

题目:学习使用按位与 。

题目&#xff1a;学习使用按位与 & 。   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 主从模式想必大家都不陌生&#xff0c;大家在学习过程中为了学习方便都在自己本地搭建了 jenkins 环境&#xff0c;然后通过 javaweb 方式实现&#xff0c;对于 docker 下实现主从模式大家好像兴趣挺大。 今天就通过这篇文章给大家讲讲怎么玩&#xff0c;希望对大家有…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

论文笔记——相干体技术在裂缝预测中的应用研究

目录 相关地震知识补充地震数据的认识地震几何属性 相干体算法定义基本原理第一代相干体技术&#xff1a;基于互相关的相干体技术&#xff08;Correlation&#xff09;第二代相干体技术&#xff1a;基于相似的相干体技术&#xff08;Semblance&#xff09;基于多道相似的相干体…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...