Stars: 172
Forks: 26
Pull Requests: 61
Issues: 26
Watchers: 4
Last Updated: 2023-08-16 06:16:37
🤖 Provide a standardized and unified response data format for Laravel and Lumen API projects. - 为 Laravel 和 Lumen API 项目提供一个规范统一的响应数据格式。
License: MIT License
Languages: PHP
为 Laravel 和 Lumen API 项目提供一个规范统一的响应数据格式。
laravel-response
主要用来统一 API 开发过程中「成功」、「失败」以及「异常」情况下的响应数据格式。
实现过程简单,在原有的 \Illuminate\Http\JsonResponse
进行封装,使用时不需要有额外的心理负担。
遵循一定的规范,返回易于理解的 HTTP 状态码,并支持定义 ResponseCodeEnum
来满足不同场景下返回描述性的业务操作码。
code
、status
、data
、message
、error
(响应格式设计源于:RESTful服务最佳实践 )JsonResponse
类中的所有 public 方法,比如 Response::success()->header('X-foo','bar');
Api Resource
、Api Resource Collection
、Paginator
(简单分页)、LengthAwarePaginator
(普通分页)、Eloquent\Model
、Eloquent\Collection
,以及简单的 array
和 string
等格式数据返回No query results for model
的异常提示修改成 数据未找到
message
别名设置为 msg
,或者 分页数据第二层的 data
改成 list
(res.data.data -> res.data.list)league/fractal
(DingoApi 使用该扩展进行数据转换)的 transformer 转换后的格式保持一致,也就是说,可以顺滑地从 Laravel Api Resource 切换到 league/fractal
jiannei/laravel-enum
)jiannei/laravel-enum
)支持 Laravel 5.5.* ~ Laravel 10.* 版本,自定义业务操作码部分依赖于 jiannei/laravel-enum,需要先进行安装。
laravel 版本 | lumen 版本 | response 版本 | enum 版本 |
---|---|---|---|
5.5.* | 5.5.* | ~1.8 | ~1.4 |
6.* | 6.* | ^2.0 | ~1.4 |
7.* | 7.* | ^3.0 | ^2.0 |
8.* | 8.* | ^4.0 | ^3.0 |
9.* - 10.* | 9.* - 10.* | ^5.0 | ^3.0 |
# laravel 5.5
composer require jiannei/laravel-response "~1.8" -vvv
composer require jiannei/laravel-enum "~1.4" -vvv # 可选
# laravel 6.x
composer require jiannei/laravel-response "^2.0" -vvv
composer require jiannei/laravel-enum "~1.4" -vvv # 可选
# laravel 7.x
composer require jiannei/laravel-response "^3.0" -vvv
composer require jiannei/laravel-enum "^2.0" -vvv # 可选
# laravel 8.x
composer require jiannei/laravel-response "^4.0" -vvv
composer require jiannei/laravel-enum "^3.0" -vvv # 可选
# laravel 9.x - 10.x
composer require jiannei/laravel-response "^5.0" -vvv
composer require jiannei/laravel-enum "^3.0" -vvv # 可选
$ php artisan vendor:publish --provider="Jiannei\Response\Laravel\Providers\LaravelServiceProvider"
// app/Exceptions/Handler.php
// 引入以后对于 API 请求产生的异常都会进行格式化数据返回
// 要求请求头 header 中包含 /json 或 +json,如:Accept:application/json
// 或者是 ajax 请求,header 中包含 X-Requested-With:XMLHttpRequest;
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
use Jiannei\Response\Laravel\Support\Traits\ExceptionTrait;
class Handler extends ExceptionHandler
{
use ExceptionTrait;
// ...
}
vendor/jiannei/laravel-response/config/response.php
,到 config/response.php
cp vendor/jiannei/laravel-response/config/response.php config/response.php
// bootstrap/app.php
$app->configure('response');
在 app/Exceptions/Handler.php
中 引入 use Jiannei\Response\Laravel\Support\Traits\ExceptionTrait;
在 app/Http/Controllers/Controller.php
中引入 use Jiannei\Response\Laravel\Support\Traits\ExceptionTrait;
$app->register(\Jiannei\Response\Laravel\Providers\LumenServiceProvider::class);
扩展包本身提供了丰富的单元测试用例tests ,也可以通过查看测试用例来解锁使用方法。
或者查看相应的模板项目:
<?php
public function index()
{
$users = User::all();
return Response::success(new UserCollection($users));
}
public function paginate()
{
$users = User::paginate(5);
return Response::success(new UserCollection($users));
}
public function simplePaginate()
{
$users = User::simplePaginate(5);
return Response::success(new UserCollection($users));
}
public function item()
{
$user = User::first();
return Response::success(new UserResource($user));
}
public function array()
{
return Response::success([
'name' => 'Jiannel',
'email' => '[email protected]'
],'', ResponseCodeEnum::SERVICE_REGISTER_SUCCESS);
}
支持自定义内层 data 字段名称,比如 rows、list
{
"status": "success",
"code": 200,
"message": "操作成功",
"data": {
"data": [
{
"nickname": "Joaquin Ondricka",
"email": "[email protected]"
},
{
"nickname": "Jermain D'Amore",
"email": "[email protected]"
},
{
"nickname": "Erich Moore",
"email": "[email protected]"
}
]
},
"error": {}
}
支持自定义内层 data 字段名称,比如 rows、list
{
"status": "success",
"code": 200,
"message": "操作成功",
"data": {
"data": [
{
"nickname": "Joaquin Ondricka",
"email": "[email protected]"
},
{
"nickname": "Jermain D'Amore",
"email": "[email protected]"
},
{
"nickname": "Erich Moore",
"email": "[email protected]"
},
{
"nickname": "Eva Quitzon",
"email": "[email protected]"
},
{
"nickname": "Miss Gail Mitchell",
"email": "[email protected]"
}
],
"meta": {
"pagination": {
"count": 5,
"per_page": 5,
"current_page": 1,
"total": 12,
"total_pages": 3,
"links": {
"previous": null,
"next": "http://laravel-api.test/api/users/paginate?page=2"
}
}
}
},
"error": {}
}
支持自定义内层 data 字段名称,比如 rows、list
{
"status": "success",
"code": 200,
"message": "操作成功",
"data": {
"data": [
{
"nickname": "Joaquin Ondricka",
"email": "[email protected]"
},
{
"nickname": "Jermain D'Amore",
"email": "[email protected]"
},
{
"nickname": "Erich Moore",
"email": "[email protected]"
},
{
"nickname": "Eva Quitzon",
"email": "[email protected]"
},
{
"nickname": "Miss Gail Mitchell",
"email": "[email protected]"
}
],
"meta": {
"pagination": {
"count": 5,
"per_page": 5,
"current_page": 1,
"links": {
"previous": null,
"next": "http://laravel-api.test/api/users/simple-paginate?page=2"
}
}
}
},
"error": {}
}
{
"status": "success",
"code": 200,
"message": "操作成功",
"data": {
"nickname": "Joaquin Ondricka",
"email": "[email protected]"
},
"error": {}
}
Response::ok();// 无需返回 data,只返回 message 情形的快捷方法
Response::localize(200101);// 无需返回 data,message 根据响应码配置返回的快捷方法
Response::accepted();
Response::created();
Response::noContent();
public function fail()
{
Response::fail();// 不需要加 return
}
{
"status": "fail",
"code": 500,
"message": "Http internal server error",
"data": {},
"error": {}
}
{
"status": "fail",
"code": 500,
"message": "操作失败",
"data": {},
"error": {}
}
public function fail()
{
Response::fail('error');// 不需要加 return
}
返回数据
{
"status": "fail",
"code": 500,
"message": "error",
"data": {},
"error": {}
}
public function fail()
{
Response::fail('',ResponseCodeEnum::SERVICE_LOGIN_ERROR);
}
返回数据
{
"status": "fail",
"code": 500102,
"message": "登录失败",
"data": {},
"error": {}
}
Response::errorBadRequest();
Response::errorUnauthorized();
Response::errorForbidden();
Response::errorNotFound();
Response::errorMethodNotAllowed();
Response::errorInternal();
{
"status": "error",
"code": 422,
"message": "验证失败",
"data": {},
"error": {
"email": [
"The email field is required."
]
}
}
可以使用 abort 辅助函数抛出 HttpException 异常
abort(500102,'登录失败');
// 返回数据
{
"status": "fail",
"code": 500102,
"message": "登录失败",
"data": {},
"error": {}
}
开启 debug(APP_DEBUG=true
)
{
"status": "error",
"code": 404,
"message": "Http not found",
"data": {},
"error": {
"message": "",
"exception": "Symfony\\Component\\HttpKernel\\Exception\\NotFoundHttpException",
"file": "/home/vagrant/code/laravel-api-starter/vendor/laravel/framework/src/Illuminate/Routing/AbstractRouteCollection.php",
"line": 43,
"trace": [
{
"file": "/home/vagrant/code/laravel-api-starter/vendor/laravel/framework/src/Illuminate/Routing/RouteCollection.php",
"line": 162,
"function": "handleMatchedRoute",
"class": "Illuminate\\Routing\\AbstractRouteCollection",
"type": "->"
},
{
"file": "/home/vagrant/code/laravel-api-starter/vendor/laravel/framework/src/Illuminate/Routing/Router.php",
"line": 646,
"function": "match",
"class": "Illuminate\\Routing\\RouteCollection",
"type": "->"
}
]
}
}
关闭 debug
{
"status": "error",
"code": 404,
"message": "Http not found",
"data": {},
"error": {}
}
<?php
namespace App\Enums;
use Jiannei\Enum\Laravel\Repositories\Enums\HttpStatusCodeEnum;
class ResponseCodeEnum extends HttpStatusCodeEnum
{
// 业务操作正确码:1xx、2xx、3xx 开头,后拼接 3 位
// 200 + 001 => 200001,也就是有 001 ~ 999 个编号可以用来表示业务成功的情况,当然你可以根据实际需求继续增加位数,但必须要求是 200 开头
// 举个栗子:你可以定义 001 ~ 099 表示系统状态;100 ~ 199 表示授权业务;200 ~ 299 表示用户业务。..
const SERVICE_REGISTER_SUCCESS = 200101;
const SERVICE_LOGIN_SUCCESS = 200102;
// 客户端错误码:400 ~ 499 开头,后拼接 3 位
const CLIENT_PARAMETER_ERROR = 400001;
const CLIENT_CREATED_ERROR = 400002;
const CLIENT_DELETED_ERROR = 400003;
const CLIENT_VALIDATION_ERROR = 422001; // 表单验证错误
// 服务端操作错误码:500 ~ 599 开头,后拼接 3 位
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;
}
<?php
// lang/zh_CN/enums.php
use App\Repositories\Enums\ResponseCodeEnum;
return [
// 响应状态码
ResponseCodeEnum::class => [
// 成功
ResponseCodeEnum::HTTP_OK => '操作成功', // 自定义 HTTP 状态码返回消息
ResponseCodeEnum::HTTP_INTERNAL_SERVER_ERROR => '操作失败', // 自定义 HTTP 状态码返回消息
ResponseCodeEnum::HTTP_UNAUTHORIZED => '授权失败',
// 业务操作成功
ResponseCodeEnum::SERVICE_REGISTER_SUCCESS => '注册成功',
ResponseCodeEnum::SERVICE_LOGIN_SUCCESS => '登录成功',
// 客户端错误
ResponseCodeEnum::CLIENT_PARAMETER_ERROR => '参数错误',
ResponseCodeEnum::CLIENT_CREATED_ERROR => '数据已存在',
ResponseCodeEnum::CLIENT_DELETED_ERROR => '数据不存在',
ResponseCodeEnum::CLIENT_VALIDATION_ERROR => '表单验证错误',
// 服务端错误
ResponseCodeEnum::SYSTEM_ERROR => '服务器错误',
ResponseCodeEnum::SYSTEM_UNAVAILABLE => '服务器正在维护,暂不可用',
ResponseCodeEnum::SYSTEM_CACHE_CONFIG_ERROR => '缓存配置错误',
ResponseCodeEnum::SYSTEM_CACHE_MISSED_ERROR => '缓存未命中',
ResponseCodeEnum::SYSTEM_CONFIG_ERROR => '系统配置错误',
// 业务操作失败:授权业务
ResponseCodeEnum::SERVICE_REGISTER_ERROR => '注册失败',
ResponseCodeEnum::SERVICE_LOGIN_ERROR => '登录失败',
],
];
非常感谢 Jetbrains 为我提供的 IDE 开源许可,让我完成此项目和其他开源项目上的开发工作。
Thanks goes to these wonderful people (emoji key):
Pham Thao 🎨 |
guanguans 🐛 |
This project follows the all-contributors specification. Contributions of any kind welcome!
MIT 许可证(MIT)。有关更多信息,请参见协议文件。