当前位置:首页 > 技术 > 正文内容

新版 Laravel 异常处理: 配置异常报告和渲染逻辑

代码老兵 技术 2026年5月20日 21

在新版的 Laravel 中,异常处理完全集中在项目的 bootstrap/app.php 文件中。从 Laravel 11 开始,就没有 app/Exceptions/Handler.php 这个文件了。

Laravel 11 对其应用骨架进行了大规模的“瘦身”,将原本分散在各个文件中的配置进行了集中管理:

  • 去掉了 app/Exceptions/Handler.php,异常处理完全移到了 bootstrap/app.phpwithExceptions() 方法中。

  • 去掉了 app/Http/Kernel.php,中间件的配置也完全移到了 bootstrap/app.phpwithMiddleware() 方法中。

  • 精简了 config/ 目录,默认只保留了最核心的几个配置文件(其他配置采用框架底层默认值,需要时可以通过命令发布出来)。

所以,现在如果你使用的是 Laravel 11、Laravel 12 或 Laravel 13,所有全局的异常捕获、重定向、API 错误返回格式,都需要直接在 bootstrap/app.php 里面写闭包来配置。


1. 核心入口点

打开 bootstrap/app.php,你会看到类似下面的结构。我们需要在 withExceptions 闭包中编写逻辑:

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
        commands: __DIR__.'/../routes/console.php',
        health: '/up',
    )
    ->withMiddleware(function (Middleware $middleware) {        // 中间件配置...
    })
    ->withExceptions(function (Exceptions $exceptions) {        // ─── 所有的异常处理逻辑写在这里 ───
    })
    ->create();

2. 常用配置场景与代码示例

你可以根据需求,在 withExceptions 闭包中链式调用或直接调用以下方法:

自定义渲染(修改 HTTP 响应)

当某个特定的异常发生时,如果你想让用户看到自定义的视图或返回特定的 JSON 数据,可以使用 render 方法:

use App\Exceptions\InvalidOrderException;
use Illuminate\Http\Request;
$exceptions->render(function (InvalidOrderException $e, Request $request) { 
    // 如果客户端请求的是 JSON 格式(比如 API 请求)
    if ($request->expectsJson()) {
        return response()->json(['error' => '订单处理失败'], 422);
    }   
    // 否则返回自定义的错误页面视图
    return response()->view('errors.invalid-order', ['message' => $e->getMessage()], 500);
});

自定义报告(发送错误到外部系统)

默认情况下,Laravel 会将异常记录到本地日志。如果你需要在发生特定错误时,将它们发送到第三方监控(如 Sentry、Logtail)或触发告警:

use App\Exceptions\PaymentFailedException;

$exceptions->report(function (PaymentFailedException $e) {    
    // 调用第三方 SDK 或发送通知邮件
    // Sentry::captureException($e);
});

忽略特定异常(不记录日志)

如果你想让某些无关紧要的异常保持沉默,不污染本地的日志文件:

use App\Exceptions\TemporaryNetworkHiccupException;

// 方式 A:直接忽略指定的异常类
$exceptions->dontReport([
    TemporaryNetworkHiccupException::class,
]);

// 方式 B:根据动态条件来决定是否忽略

$exceptions->dontReportWhen(function (Throwable $e) {
    return $e instanceof TemporaryNetworkHiccupException && $e->getCode() === 200;
});

强制让特定路由返回 JSON

有时不管客户端是否带有 Accept: application/json 请求头,你都希望 API 路由在出错时能够强制返回 JSON 响应:

use Illuminate\Http\Request;
use Throwable;

$exceptions->shouldRenderJsonWhen(function (Request $request, Throwable $e) {
    // 如果请求路径以 api/ 或 admin/api/ 开头,强制返回 JSON 错误
    if ($request->is('api/*') || $request->is('admin/api/*')) {
        return true;
    }
    return $request->expectsJson();
});

修改特定异常的日志级别

有些第三方包抛出的异常可能会被 Laravel 默认记录为 ERRORCRITICAL。如果你觉得它没那么严重,可以降低它的日志等级:

use PDOException;
use Psr\Log\LogLevel;

// 将数据库连接异常的日志级别提升为最高级的 CRITICAL
$exceptions->level(PDOException::class, LogLevel::CRITICAL);

3. 完整配置示例

在实际项目中,你可以将这些配置组合在一起,写成一个清晰、干净的闭包:

->withExceptions(function (Exceptions $exceptions) {    
    // 1. 调整日志等级
    $exceptions->level(PaymentException::class, Psr\Log\LogLevel::WARNING);
    
    // 2. 忽略不需要记录日志的异常
    $exceptions->dontReport([
        MissingTokenException::class,
    ]);    
    
    // 3. 自定义特定异常的返回格式
    $exceptions->render(function (AccountSuspendedException $e) {
        return response()->json(['message' => '您的账号已被冻结。'], 403);
    });
})


标签: Laravel

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。