filp/whoops 这个错误处理类库有什么好处我这里就不赘述了,谁用谁知道。
Laravel 在 4.x 时代是有集成了 whoops 的,但是在 5.x 去掉了。不过作为一个 out-of-the-box 的错误处理类库,我们依然可以很方便地将 whoops 带回 Laravel 中。
网上有很多文章都讲述了 Laravel 使用 whoops 的方法,但总有些小问题(像是代码太丑了啊,代码太丑了啊之类的)。其中我认为最优雅的实现是这篇文章所描述的: Bringing Whoops Back to Laravel 5 ,我下面的也是基于他给出的代码修改的。
安装 whoops 之类的步骤我这里就不说了,这些在它的 README 上都有。安装完后打开 app/Exceptions/Handler.php
这个文件,进行如下修改:
/** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $e * @return \Illuminate\Http\Response */ public function render($request, Exception $e) { if ($e instanceof \Illuminate\Foundation\Validation\ValidationException) { // quick fix for returning 422 // @see https://prinzeugen.net/custom-responses-of-laravel-validations/ return $e->getResponse()->setStatusCode(200); } foreach ($this->dontReport as $type) { if ($e instanceof $type) { return parent::render($request, $e); } else { // 当不处于 DEBUG 模式时隐藏错误的详细信息,防止敏感信息泄露 if (config('app.debug')) { return $this->renderExceptionWithWhoops($e); } else { // 这里我们调用下面定义的方法,给用户显示一个「哎呀,出错啦」的友好页面 // 如果你想继续使用 Laravel 默认的那个只有一句话的错误页 // 就把下面这行改成 return parent::render($request, $e); return $this->renderExceptionInBrief($e); } } } } /** * Render an exception using Whoops. * * @param \Exception $e * @return \Illuminate\Http\Response */ protected function renderExceptionWithWhoops(Exception $e) { $whoops = new \Whoops\Run; // 只有在 GET 请求出错时渲染 PrettyPage,其余请求时直接渲染文本 // 你也不想在 AJAX 请求的错误处理函数中看到一个 web 页面吧 $handler = ($_SERVER['REQUEST_METHOD'] == "GET") ? new \Whoops\Handler\PrettyPageHandler : new \Whoops\Handler\PlainTextHandler; $whoops->pushHandler($handler); return new \Illuminate\Http\Response( $whoops->handleException($e), $e->getStatusCode(), $e->getHeaders() ); } /** * Render an exception in a short word. * * @param \Exception $e * @return \Illuminate\Http\Response */ protected function renderExceptionInBrief(Exception $e) { // 这里请自定义要返回的视图,其中不包含错误的详细信息 return response()->view('errors.brief'); }
可以看到我们新添加了 renderExceptionWithWhoops
和 renderExceptionInBrief
两个方法,分别适用于 APP_DEBUG
开和关的情况。
你问我为啥要覆盖 Laravel 在 APP_DEBUG
为关时的默认错误页?
你要是觉得这个默认的页面好看那我也管不着咯~ 反正我是修改成下面这样了:
至于为什么要在当前为 POST 请求时使用 PlainTextHandler
渲染纯文本的堆栈信息:
如果你渲染的是页面的话你就会在这个 Modal 里看到你的窗口了(笑)。当然,如果你没有做这样的 Ajax 错误处理的话也可以忽略这个。
那段修改 ValidationException
响应状态码为 200
的也是为了 Ajax,详情可以查看我之前写的博文: 自定义 Laravel Validator 所返回的响应
最后效果如下:
以上。