Laravel 11自定义ExceptionHandler:如何获取错误HTML内容
Laravel 11 异常邮件通知迁移方案
核心思路
利用Laravel 11的withExceptions闭包,在异常上报流程中临时开启app.debug,生成带Ignition的详细错误HTML,发送邮件后恢复原配置,同时保留Laravel默认的错误响应页面。
实现步骤
1. 在bootstrap/app.php中配置异常处理
找到withExceptions闭包,添加自定义的reportable逻辑:
->withExceptions(function (Exceptions $exceptions) { $exceptions->reportable(function (Throwable $e) { // 仅在生产环境处理,且排除无需上报的异常(如404、419) if (app()->environment('production') && !app(\Illuminate\Foundation\Exceptions\Handler::class)->shouldntReport($e)) { $originalDebug = config('app.debug'); try { // 临时开启debug模式 config(['app.debug' => true]); // 获取当前请求实例 $request = request(); $handler = app(\Illuminate\Foundation\Exceptions\Handler::class); // 通过反射调用protected的render方法生成详细错误HTML $reflectionRender = new \ReflectionMethod($handler, 'render'); $reflectionRender->setAccessible(true); $debugResponse = $reflectionRender->invoke($handler, $request, $e); $htmlError = $debugResponse->getContent(); // -------------------------- // 这里替换为你的邮件发送逻辑 // 示例: // \Illuminate\Support\Facades\Mail::raw($htmlError, function ($message) { // $message->to('admin@your-domain.com') // ->subject('Laravel 应用异常通知'); // }); // -------------------------- } finally { // 恢复原debug配置,避免影响后续请求 config(['app.debug' => $originalDebug]); } } }); // 保留Laravel默认的错误视图配置(如需自定义可在这里添加) // $exceptions->view(function (Throwable $e) { // return match(true) { // $e instanceof NotFoundHttpException => response()->view('errors.404', [], 404), // default => response()->view('errors.500', [], 500), // }; // }); })
2. 关键细节说明
- 使用
reportable而非renderable:reportable专注于异常上报逻辑,不会干扰用户端的错误响应,完美实现「开发者收详细错误、用户看默认页面」的需求。 - 反射调用
render方法:由于Laravel 11中Handler的render方法为protected,通过反射临时开放访问权限,生成带Ignition的完整错误HTML。 - finally块恢复配置:确保无论是否发送邮件成功,都会恢复原
app.debug值,避免影响后续请求的错误展示。 - 异常过滤:通过
shouldntReport排除Laravel默认忽略的异常(如404页面不存在、CSRF令牌过期等),减少无效邮件通知。
3. 可选优化
- 添加异常上下文:可以在邮件中附加请求信息,方便排查问题:
$context = [ 'url' => $request->fullUrl(), 'method' => $request->method(), 'user' => auth()->user()?->email ?? '未登录用户', 'timestamp' => now()->format('Y-m-d H:i:s'), ]; // 将$context传入邮件视图或作为附件发送 - 异步发送邮件:避免邮件发送阻塞请求响应,使用Laravel队列异步处理:
\Illuminate\Support\Facades\Mail::to('admin@your-domain.com') ->queue(new \App\Mail\ExceptionReportMail($htmlError, $context));
内容的提问来源于stack exchange,提问作者Álvaro
相关产品推荐
相关产品推荐

