之前的一篇文章介绍了 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\Exceptions
的unauthenticated()
方法来处理的。默认情况下,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 公众号,定期送书送福利!