本文目录导读:

在PHP项目中统一处理接口异常返回,通常有几种常见且推荐的做法,以下是几种成熟的解决方案:
基于异常处理的统一返回方案(推荐)
自定义异常类
<?php
// App\Exceptions\ApiException.php
class ApiException extends \Exception
{
protected $statusCode;
protected $data;
public function __construct($message = "", $code = 0, $statusCode = 400, $data = null)
{
parent::__construct($message, $code);
$this->statusCode = $statusCode;
$this->data = $data;
}
public function getStatusCode()
{
return $this->statusCode;
}
public function getData()
{
return $this->data;
}
}
统一响应类
<?php
// App\Http\Response\ApiResponse.php
class ApiResponse
{
public static function success($data = null, $message = 'Success', $code = 200)
{
return json_encode([
'code' => $code,
'message' => $message,
'data' => $data,
'timestamp' => time()
]);
}
public static function error($message = 'Error', $code = 400, $data = null)
{
return json_encode([
'code' => $code,
'message' => $message,
'data' => $data,
'timestamp' => time()
]);
}
public static function exception(\Exception $exception)
{
$code = $exception->getCode() ?: 500;
$message = $exception->getMessage() ?: 'Internal Server Error';
// 生产环境隐藏错误详情
if (env('APP_ENV') === 'production') {
$message = 'Internal Server Error';
}
return self::error($message, $code);
}
}
全局异常处理器
<?php
// App\Exceptions\Handler.php
class Handler
{
public function render($request, \Exception $exception)
{
// 如果是API请求
if ($this->isApiRequest($request)) {
// 自定义异常处理
if ($exception instanceof ApiException) {
return ApiResponse::exception($exception);
}
// 其他异常处理
return ApiResponse::exception($exception);
}
// 非API请求交给默认处理
return parent::render($request, $exception);
}
private function isApiRequest($request)
{
return $request->expectsJson() ||
strpos($request->path(), 'api/') === 0;
}
}
中间件方案(适用于框架)
Laravel 示例
<?php
// app/Http/Middleware/ApiResponseMiddleware.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\JsonResponse;
class ApiResponseMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// 只处理API路由
if ($request->is('api/*')) {
return $this->formatResponse($response);
}
return $response;
}
protected function formatResponse($response)
{
if ($response instanceof JsonResponse) {
$original = $response->getData(true);
// 统一包装响应格式
$formatted = [
'code' => $response->getStatusCode(),
'message' => $original['message'] ?? 'Success',
'data' => $original['data'] ?? $original,
'timestamp' => time()
];
return response()->json($formatted);
}
return $response;
}
}
简单实用的统一处理类
<?php
// App\Helpers\ApiHelper.php
class ApiHelper
{
// 成功响应
public static function success($data = [], $message = '操作成功')
{
return self::response(200, $message, $data);
}
// 错误响应
public static function error($message = '操作失败', $code = 400, $data = [])
{
return self::response($code, $message, $data);
}
// 未授权
public static function unauthorized($message = '未授权访问')
{
return self::response(401, $message);
}
// 参数错误
public static function validationError($errors = [])
{
return self::response(422, '参数验证失败', $errors);
}
// 服务器错误
public static function serverError($message = '服务器内部错误')
{
return self::response(500, $message);
}
// 基础响应方法
private static function response($code, $message, $data = null)
{
$response = [
'code' => $code,
'message' => $message,
'data' => $data,
'timestamp' => time()
];
header('Content-Type: application/json; charset=utf-8');
echo json_encode($response, JSON_UNESCAPED_UNICODE);
exit;
}
}
使用示例
<?php
// 控制器中使用
class UserController
{
public function login()
{
try {
// 业务逻辑
$user = User::find($id);
if (!$user) {
// 触发自定义异常
throw new ApiException('用户不存在', 1001, 404);
}
// 成功返回
return ApiHelper::success($user, '登录成功');
} catch (ApiException $e) {
// 自定义异常处理
return ApiHelper::error($e->getMessage(), $e->getCode());
} catch (\Exception $e) {
// 其他异常处理
Log::error($e->getMessage());
return ApiHelper::serverError();
}
}
public function validate()
{
// 验证失败示例
$errors = ['name' => '用户名不能为空'];
return ApiHelper::validationError($errors);
}
}
响应格式建议
{
"code": 200,
"message": "成功",
"data": {
"user": {
"id": 1,
"name": "张三"
}
},
"timestamp": 1620000000
}
推荐方案选择
- 小型项目:使用 ApiHelper 简单类,直接调用静态方法
- 中大型项目:使用自定义异常 + 全局异常处理器
- 框架项目:使用中间件方案,统一拦截处理
这样设计的好处:
- 统一的错误格式
- 便于前端统一处理
- 代码复用性高
- 易于维护和扩展