本文目录导读:

在 Laravel 中,异常码的映射通常指将 HTTP 状态码与自定义异常关联,或将异常类型转换为特定的响应格式,以下是几种常见的实现方式:
基础的异常映射(App\Exceptions\Handler)
在 app/Exceptions/Handler.php 中定义映射:
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
class Handler extends ExceptionHandler
{
protected $dontReport = [
// 不记录到日志的异常类型
];
public function register()
{
$this->reportable(function (Throwable $e) {
//
});
// 自定义异常映射
$this->renderable(function (NotFoundHttpException $e, $request) {
if ($request->expectsJson()) {
return response()->json([
'message' => '资源未找到',
'code' => 404
], 404);
}
return response()->view('errors.404', [], 404);
});
$this->renderable(function (MethodNotAllowedHttpException $e, $request) {
return response()->json([
'message' => '请求方法不允许',
'code' => 405
], 405);
});
}
// 自定义异常响应方法
public function render($request, Throwable $e)
{
if ($request->expectsJson()) {
return $this->handleApiException($request, $e);
}
return parent::render($request, $e);
}
protected function handleApiException($request, Throwable $e)
{
$exception = $this->prepareException($e);
if ($exception instanceof \Illuminate\Http\Exception\HttpResponseException) {
return $exception->getResponse();
}
if ($exception instanceof \Illuminate\Auth\AuthenticationException) {
return $this->unauthenticated($request, $exception);
}
if ($exception instanceof \Illuminate\Validation\ValidationException) {
return $this->convertValidationExceptionToResponse($exception, $request);
}
$statusCode = $this->getStatusCode($exception);
return response()->json([
'message' => $exception->getMessage(),
'code' => $statusCode,
'errors' => []
], $statusCode);
}
protected function getStatusCode($exception)
{
if ($exception instanceof \Symfony\Component\HttpKernel\Exception\HttpException) {
return $exception->getStatusCode();
}
return 500; // 默认服务器错误
}
}
自定义异常类
创建具有特定状态码的自定义异常:
// app/Exceptions/CustomException.php
namespace App\Exceptions;
use Exception;
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
class CustomException extends Exception implements HttpExceptionInterface
{
protected $statusCode;
protected $headers = [];
public function __construct($message = "", $statusCode = 400, $code = 0, Exception $previous = null)
{
$this->statusCode = $statusCode;
parent::__construct($message, $code, $previous);
}
public function getStatusCode()
{
return $this->statusCode;
}
public function getHeaders()
{
return $this->headers;
}
public function setHeaders(array $headers)
{
$this->headers = $headers;
}
}
// app/Exceptions/BusinessException.php
namespace App\Exceptions;
class BusinessException extends CustomException
{
const CODE_USER_NOT_FOUND = 1001;
const CODE_ORDER_INVALID = 1002;
const CODE_PAYMENT_FAILED = 1003;
private static $messages = [
self::CODE_USER_NOT_FOUND => '用户不存在',
self::CODE_ORDER_INVALID => '订单无效',
self::CODE_PAYMENT_FAILED => '支付失败',
];
public function __construct($code = 0, $message = '')
{
if (empty($message) && isset(self::$messages[$code])) {
$message = self::$messages[$code];
}
parent::__construct($message, 422, $code);
}
}
映射异常到特定响应
// app/Exceptions/Handler.php
public function register()
{
// 业务异常映射
$this->renderable(function (BusinessException $e, $request) {
return response()->json([
'status' => 'error',
'code' => $e->getCode(),
'message' => $e->getMessage(),
'http_code' => $e->getStatusCode()
], $e->getStatusCode());
});
// 模型未找到异常
$this->renderable(function (\Illuminate\Database\Eloquent\ModelNotFoundException $e, $request) {
return response()->json([
'message' => '数据未找到',
'code' => 404
], 404);
});
// 授权异常
$this->renderable(function (\Illuminate\Auth\Access\AuthorizationException $e, $request) {
return response()->json([
'message' => '没有权限执行此操作',
'code' => 403
], 403);
});
}
使用异常码映射表
创建映射配置文件:
// config/errorcodes.php
return [
'VALIDATION_ERROR' => [
'http_code' => 422,
'message' => '验证错误'
],
'AUTHENTICATION_FAILED' => [
'http_code' => 401,
'message' => '认证失败'
],
'FORBIDDEN' => [
'http_code' => 403,
'message' => '禁止访问'
],
'NOT_FOUND' => [
'http_code' => 404,
'message' => '资源未找到'
],
'INTERNAL_ERROR' => [
'http_code' => 500,
'message' => '服务器内部错误'
],
'BUSINESS_ERROR' => [
'http_code' => 400,
'message' => '业务处理错误'
],
];
// 创建错误码异常类
namespace App\Exceptions;
class ErrorCodeException extends \Exception
{
protected $httpCode;
public function __construct($errorCode, $message = null)
{
$config = config("errorcodes.{$errorCode}");
if (!$config) {
$config = [
'http_code' => 500,
'message' => '未知错误'
];
}
$this->httpCode = $config['http_code'];
$message = $message ?? $config['message'];
parent::__construct($message, $config['http_code']);
}
public function getHttpCode()
{
return $this->httpCode;
}
}
// 使用
throw new ErrorCodeException('VALIDATION_ERROR', '自定义消息');
在控制器中使用
use App\Exceptions\BusinessException;
class UserController extends Controller
{
public function show($id)
{
$user = User::find($id);
if (!$user) {
throw new BusinessException(BusinessException::CODE_USER_NOT_FOUND);
}
return response()->json($user);
}
}
状态码与异常类型映射表
| HTTP状态码 | 异常类型 | 常用场景 |
|---|---|---|
| 400 | BadRequestHttpException | 无效请求参数 |
| 401 | AuthenticationException | 未认证 |
| 403 | AuthorizationException | 无权限 |
| 404 | NotFoundHttpException | 资源不存在 |
| 405 | MethodNotAllowedHttpException | 不支持的HTTP方法 |
| 409 | ConflictHttpException | 资源冲突 |
| 422 | ValidationException | 验证失败 |
| 429 | TooManyRequestsHttpException | 请求频率限制 |
| 500 | HttpException | 服务器错误 |
通过以上方式,你可以灵活地将 Laravel 异常映射到特定的状态码和响应格式。