之前的一篇文章介绍了 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 公众号,定期送书送福利!