Laravel 异常处理

JellyBool

JellyBool

之前的一篇文章介绍了 Laravel 的异常和日志的一些情况,本文来看看 Laravel 在处理异常返回的时候是什么样的流程。

在 Laravel 的项目中,出现异常的时候,Laravel 会默认去寻找这个类中是否存在 render() 这个方法,因为这个方法是负责处理渲染异常信息的。所以你要自定义异常的返回信息的话,可以直接在 render() 方法里面实现,这都是看你自己的需求。

在通常情况下,Laravel 会自动将异常信息分为两种格式来处理:HTML 或者 JSON。而在这之前,它会把基本所有的异常信息先处理为 HTTPException

if ($e instanceof ModelNotFoundException) {

    $e = new NotFoundHttpException($e->getMessage(), $e);

} elseif ($e instanceof AuthorizationException) {

    $e = new HttpException(403, $e->getMessage());

} elseif ($e instanceof TokenMismatchException) {

    $e = new HttpException(419, $e->getMessage());

}

后面讲一下 Laravel 常见的异常处理。

认证异常处理

认证异常是指Illuminate\Auth\AuthenticationException,这个是由 App\Exceptionsunauthenticated() 方法来处理的。默认情况下,laravel 会将用户重定向到 /login URL 中,但是如果你是期望返回 JSON 数据的话,大概返回的信息如下:

{"message" : "Unauthenticated."}

表单验证异常处理

其实在表单验证不通过的时候,如果我们使用的是传统的重定向到某个页面中,我们通常会使用类似下面的代码来提示错误信息:

@if (count($errors) > 0)

    <div class="alert alert-danger">

        <ul>

            @foreach ($errors->all() as $error)

                <li>{{ $error }}</li>

            @endforeach

        </ul>

    </div>

@endif

其实表单验证出错的时候也是可以直接使用 JSON 的格式返回的,这个时候需要注意的是,返回的 HTTP 状态码是 422

{

  "message": "The given data failed to pass validation.",

  "errors": {

    "name": [

        "The name field is required.",

        "The name field must be a string."

    ]

  }

}

其他的异常处理

目前来说,Laravel 也是直接将大多数的异常转化为 HTTPException,但是某些情况下我们还是需要自己去处理异常的返回信息,这个时候怎么办?

使用 expectsJson() !这个方法可以非常easy地实现我们队 JSON 返回的需求!expectsJson() 主要是通过指定一个特定的 X-Requested-With header 来实现的,如果这个 header 携带 XMLHttpRequest 的值的话,Laravel 就认为我们期望返回的是 JSON 格式的异常信息。如果说你使用 Laravel 推荐的 axios 的话,在 assets 下的 bootstrap.js 文件就可以看到,Laravel 官方就会为你指定这个 header:

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

所以在我们使用expectsJson()返回异常信息的时候,大概的格式是下面这样:

{

    "message": "...",

    "file": "...",

    "line": 0,

    "trace": "..."

}

我们在前端处理的时候通常就是取 message 就好了。

那如果说是正常的 HTML 的返回格式呢?这个时候,其实你就可以在 resources/views/errors 定义一个 500.blade.php 文件,Laravel 会默认先展示这个视图文件的内容。如果没有自定义,那就返回那个常见的 :

Whoops, looks like something went wrong.

总结

Laravel 的异常处理通常会转化为 HTTPException,而且我们在使用 AJAX 的时候也是可以直接用 expectsJson() 来判断返回什么格式的信息。这样基本上解决了 90% 以上的应用场景了。

关注 codecasts 公众号,定期送书送福利!

本文由 JellyBool 创作, 转载和引用遵循 署名-非商业性使用 2.5 中国大陆 进行许可。

共有 0 条评论