Laravel异常码怎么映射

wen PHP项目 7

本文目录导读:

Laravel异常码怎么映射

  1. 基础的异常映射(App\Exceptions\Handler)
  2. 自定义异常类
  3. 映射异常到特定响应
  4. 使用异常码映射表
  5. 在控制器中使用
  6. 状态码与异常类型映射表

在 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 异常映射到特定的状态码和响应格式。

抱歉,评论功能暂时关闭!