Laravel仿Java对Exception统一处理

以Spring开发为例,通过ExceptionHandler,可以对业务中抛出的异常进行捕捉而后统一处理,避免了接口或页面对外暴露不友好的堆栈异常信息,规范了异常处理流程,并且减少了代码编写过程中额外的return。


Laravel已经预先定义了一些异常,如ModelNotFoundException、MassAssignmentException等,但是我们通常需要更业务化的定制以及更友好的异常处理流程,于是可以通过修改Laravel提供的Handler来满足需求。


Laravel的异常处理器在app/Exceptions/Handler.php文件中,一般只需要修改render()方法即可,如

/**
     * Render an exception into an HTTP response.
     *
     * @param  IlluminateHttpRequest  $request
     * @param  Exception  $exception
     * @return IlluminateHttpResponse
     */
    public function render($request, Exception $exception) {
        // 仅捕捉指定类别的异常类型
        if ($exception instanceof ArgumentValidationException
            || $exception instanceof BusinessException
            || $exception instanceof BusinessHttpException
            || $exception instanceof ObjectNotFoundException
        ) {
            // 避免过多的堆栈信息,最多只输出5条
            $publish_trace_length = count($exception->getTrace());
            $publish_trace_length = $publish_trace_length >= 5 ? 5 : $publish_trace_length;
            $traceArr = array_slice($exception->getTrace(), 0, $publish_trace_length);
            // 对未定义异常码的异常进行Http Code转换
            $exceptionCode = $exception->getCode() > 0 ? $exception->getCode() : 400;
            // 以json形式输出异常
            return response()->json([
                'msg' => $exception->getMessage(),
                'code' => $exception->getCode(),
                'detail' => $traceArr
            ], $exceptionCode);
        } else {
            return parent::render($request, $exception);
        }
    }


然后具体业务异常的定义可以在任意目录(通常在app/Exceptions)下,具体定义如:

/**
 * 参数异常
 * Class BusinessHttpException
 * @package SymfonyComponentHttpKernelException
 */
class ArgumentValidationException extends HttpException {

    public static $http_code = 400;

    /**
     * Constructor.
     *
     * @param string $message The internal exception message
     * @param Exception $previous The previous exception
     * @param int $code The internal exception code
     */
    public function __construct($message = null, $code = 0, Exception $previous = null) {
        parent::__construct(self::$http_code, $message, $previous, array(), $code);
    }
}

于是在业务中我们可以直接throw new ArgumentValidationException('异常内容')即可。