本文目录导读:

在PHP中统一返回数据格式是一个很好的实践,它能让前后端协作更顺畅,也便于后期的维护和扩展,下面提供几种常见且实用的统一方案:
JSON 格式(最推荐,适用于现代 Web 应用/API)
这是目前使用最广泛的方式,特别适合前后端分离的项目。
定义一个统一的返回函数
<?php
/**
* 统一返回 JSON 数据格式
*
* @param int $code 状态码(200 成功,400 参数错误,401 未登录,404 不存在,500 服务器错误)
* @param string $message 提示信息
* @param mixed $data 业务数据(可选,默认 null)
* @param array $extra 额外字段(可选,用于扩展一些头信息等)
* @return \Illuminate\Http\JsonResponse|\think\response\Json
*/
function apiResponse($code = 200, $message = 'success', $data = null, $extra = [])
{
// 1. 构建统一的数据结构
$response = [
'code' => $code, // 业务状态码
'message' => $message, // 提示信息
'data' => $data, // 业务数据
'timestamp' => time(), // 时间戳,便于调试
];
// 2. 如果有额外的自定义字段,合并进去
$response = array_merge($response, $extra);
// 3. 返回 JSON 响应
return json($response); // Laravel 写法
// 或者 return response()->json($response); // 通用 PHP 写法
// 或者 return json_encode($response); // 纯 PHP 写法,需配合 header 设置
}
使用示例
// 成功返回(带数据) return apiResponse(200, '获取成功', ['id' => 1, 'name' => '张三']); // 成功返回(无数据) return apiResponse(200, '删除成功'); // 失败返回 return apiResponse(400, '参数错误:username 不能为空'); // 未授权 return apiResponse(401, '请先登录'); // 服务器错误 return apiResponse(500, '系统繁忙,请稍后再试');
对应的前端解析
// 前端 fetch 或 axios 解析
fetch('/api/user/1')
.then(res => res.json())
.then(result => {
if (result.code === 200) {
console.log('成功:', result.data);
} else {
console.log('失败:', result.message);
}
});
使用自定义类或 Trait(适合大型项目)
可以将返回逻辑封装成类,更规范,也方便 IDE 提示。
<?php
namespace App\Traits;
trait ApiResponse
{
/**
* 成功响应
*/
protected function success($data = null, $message = 'success', $code = 200)
{
return $this->response($code, $message, $data);
}
/**
* 失败响应
*/
protected function error($message = 'error', $code = 400, $data = null)
{
return $this->response($code, $message, $data);
}
/**
* 核心响应方法
*/
protected function response($code, $message, $data)
{
return response()->json([
'code' => $code,
'message' => $message,
'data' => $data,
'timestamp' => time(),
]);
}
/**
* 列表分页响应(常用)
*/
protected function paginate($paginator, $message = 'success')
{
return $this->success([
'items' => $paginator->items(),
'total' => $paginator->total(),
'current_page' => $paginator->currentPage(),
'per_page' => $paginator->perPage(),
'last_page' => $paginator->lastPage(),
], $message);
}
}
处理 HTTP 状态码
除了业务状态码,还应该将 HTTP 状态码与业务状态码对应起来,这样浏览器和前端都能正确识别。
| 场景 | 业务码 (code) | HTTP 状态码 |
|---|---|---|
| 成功 | 200 | 200 |
| 参数校验失败 | 400 | 200/400 |
| 未登录/登录过期 | 401 | 200/401 |
| 无权限 | 403 | 200/403 |
| 资源不存在 | 404 | 200/404 |
| 服务器内部错误 | 500 | 200/500 |
注意: 通常业务码用于前端逻辑判断,HTTP 状态码用于浏览器和网络层面的判断,现在很多团队约定统一返回
200 HTTP 状态码+ 业务码,这样前端统一走success回调;也可以 HTTP 状态码和业务码都真实返回,前端捕获错误更规范。
// 推荐:两者都真实对应
public function login(Request $request)
{
if (!auth()->attempt($request->only('email','password'))) {
return response()->json([
'code' => 401,
'message' => '账号或密码错误',
'data' => null,
], 401); // 同时设置 HTTP 状态码为 401
}
$user = auth()->user();
return response()->json([
'code' => 200,
'message' => '登录成功',
'data' => ['token' => $user->createToken('auth')->plainTextToken],
], 200);
}
全局异常处理器(统一兜底)
无论代码哪里出了异常,都统一走这个格式返回,避免散落的错误格式。
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
class Handler extends ExceptionHandler
{
public function render($request, Throwable $e)
{
// 如果是 API 请求,统一返回 JSON
if ($request->expectsJson() || $request->is('api/*')) {
$code = $e->getCode() && in_array($e->getCode(), [200, 400, 401, 403, 404, 422, 500]) ? $e->getCode() : 500;
return response()->json([
'code' => $code,
'message' => $e->getMessage(),
'data' => null,
'timestamp' => time(),
], $code === 500 ? 500 : 200); // 500 用真实 HTTP 状态码,其它统一 200
}
return parent::render($request, $e);
}
}
总结建议
| 项目类型 | 推荐方案 |
|---|---|
| 前后端分离的 Web 应用 | 方案一 + 方案三(JSON + 业务码) |
| 大型后台管理系统 | 方案二(Trait 方式) |
| 高并发、微服务 API | 方案一 + 引入统一 SDK 或中间件 |
| 所有项目 | 确保全局异常统一 |
核心要点:
code:业务状态码,用于前端逻辑判断message:人类可读的提示信息data:业务数据(成功)、null(失败)timestamp:时间戳,便于排查问题- HTTP 状态码尽量与业务码一致或至少保证 500 的错误正确返回
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播