跳转到主要内容

概述

新建一个 Laravel 项目时,错误与异常的处理都是开箱即用的。 自定义配置可以通过 bootstrap/app.php 中的 withExceptions 方法进行。

异常处理流程

下面展示了从异常抛出到响应返回给客户端的过程。
withExceptions 闭包中的 $exceptions 对象是 Illuminate\Foundation\Configuration\Exceptions 的实例,负责管理整个应用的异常处理。

调试设置

config/app.php 中的 debug 选项控制错误信息展示的详细程度。 默认情况下,它会读取 .envAPP_DEBUG 环境变量的值。
在生产环境中请务必将 APP_DEBUG 设为 false。若保持 true,可能会向最终用户暴露敏感信息。

异常的报告

异常报告指的是将异常记录到日志,或发送到 SentryFlare 等外部服务。 默认情况下会根据 config/logging.php 的设置写入日志。

自定义报告回调

若希望不同类型的异常有不同的报告逻辑,可以给 report 方法传入一个闭包。 Laravel 会根据闭包的类型提示判断适用的异常类型。
即便注册了自定义回调,默认的日志记录仍会继续。 如果要阻止向默认处理传播,可以调用 stop(),或返回 false

report() 辅助函数

如果只想报告异常而不显示错误页面,可以使用 report() 辅助函数。
report() 辅助函数可以在不中断用户响应的情况下记录错误,非常适合后台任务或不重要处理中的异常处理。

防止重复报告

如果同一个异常实例多次被传给 report(),日志中可能会出现重复条目。 设置 dontReportDuplicates() 后,同一个实例只会在第一次时被记录。

全局日志上下文

若要给所有异常日志添加公共信息,可以使用 context 方法。 如果可用,Laravel 会自动附加当前用户 ID。

给异常类添加 context() 方法

在异常类自身上定义 context() 方法,就能在日志中加入该异常特有的上下文信息。

修改日志级别

若要以特定日志级别记录某个异常,可以使用 level 方法。

异常报告的节流

出现大量异常时,可以通过 throttle 方法控制报告数量。
若要按每分钟条数限制,可以使用 Limit

异常的渲染

渲染就是把异常转换为 HTTP 响应的过程。 默认情况下 Laravel 会自动生成合适的响应,但也可以自定义。

自定义渲染回调

render 方法传入闭包即可把异常转换为响应。
内置异常(如 NotFoundHttpException)的渲染也可以被覆盖。 如果闭包没有返回值,就会退回默认渲染。

自动判断 JSON / HTML

Laravel 会根据请求的 Accept 头自动判断返回 HTML 还是 JSON。 如果需要自定义这一逻辑,可以使用 shouldRenderJsonWhen

自定义整个响应

使用 respond 方法可以对生成的响应进行进一步处理。

自定义异常类

你可以在 app/Exceptions/ 目录下创建自己的异常类。 如果在异常类中定义了 report()render() 方法,即使不在 bootstrap/app.php 中配置,它们也会被自动调用。

创建异常类

1

创建异常类

2

实现 report() 与 render()

report() 方法可以通过类型提示使用依赖注入,Laravel 的服务容器会自动解析。

ShouldntReport 接口

对于不需要报告的异常,可以实现 ShouldntReport 接口。 实现了这个接口的异常将不会被报告。

抛出异常

abort() 辅助函数

可以在应用的任何位置抛出 HTTP 错误响应。

abort_if() / abort_unless()

用于按条件抛出异常的辅助函数。
在控制器或中间件中做权限检查时非常方便,也常与 Gate 或策略搭配使用。

异常的全局控制

忽略特定异常

使用 dontReport 指定不上报的异常。自定义的渲染逻辑仍然生效。
如果要按条件忽略,可以给 dontReportWhen 传入闭包。
Laravel 默认会自动忽略部分异常,比如 404、CSRF Token 无效 (419)、来源不一致 (403) 等。

让 Laravel 恢复上报默认忽略的异常

要让默认被忽略的异常重新参与报告,可以使用 stopIgnoring

HTTP 错误页面

Laravel 允许为不同的 HTTP 状态码定义自定义错误视图。

创建自定义错误视图

resources/views/errors/ 目录下,以状态码为文件名创建 Blade 模板。
视图内可以通过 $exception 变量访问错误信息。

发布默认错误模板

如果希望在 Laravel 自带的错误页面基础上定制,可以通过 vendor:publish 获取。

兜底错误页面

对于没有对应状态码视图的情况,可以创建 4xx.blade.php5xx.blade.php 作为兜底。
Laravel 已经为 404500503 提供了默认页面。如果要定制这些,请创建单独文件(例如 404.blade.php)而非依赖兜底。

实战示例:API 异常处理器

在提供 API 的应用中,异常始终需要以 JSON 返回。 下面是一个在 bootstrap/app.php 中集中管理 API 错误的示例实现。

自定义 API 异常类的实现

创建一个 API 专用的基础异常类,可以让每个接口返回一致的错误响应。
在控制器中使用示例:

小结

  • 只需创建如 resources/views/errors/404.blade.php 之类的文件即可自动生效
  • 视图内可通过 $exception 变量访问错误详情
  • 可通过 php artisan vendor:publish --tag=laravel-errors 获取默认模板
  • 通过 4xx.blade.php / 5xx.blade.php 可定义兜底错误页
  • 一定要设置 APP_DEBUG=false,避免把堆栈信息暴露给用户
  • 接入 Sentry、Flare 等外部错误追踪服务,集中管理错误
  • 使用 throttle() 避免大量异常时日志被淹没
  • API 接口保持一致的 JSON 错误响应格式
最后修改于 2026年7月18日