Yii 2 错误处理完全指南:ErrorHandler 组件、异常页面定制与多格式错误响应
Yii 2 错误处理完全指南ErrorHandler 组件、异常页面定制与多格式错误响应【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址: https://gitcode.com/gh_mirrors/yi/yii2本篇技术指南以 Yii 2 内置的yii\web\ErrorHandler错误处理器为核心系统讲解它在 Web 应用请求生命周期参见 runtime-overview.md中如何接管 PHP 错误与异常从“非致命错误转异常”的底层机制、YII_DEBUG与YII_ENABLE_ERROR_HANDLER常量的行为差异到使用errorAction自定义错误页面、以及按response组件格式输出 HTML / JSON / RAW 错误响应的完整方案。读完本文你将掌握在 Yii 2 应用里统一、安全、可定制地处理错误与异常的全部关键技术。错误处理器能为你做什么Yii 内置的yii\web\ErrorHandler错误处理器把 PHP 原本“粗糙”的错误处理变成了一种愉悦的体验。它主要做了四件事把全部非致命 PHP 错误如 warning、notice转换为可捕获的异常从而让try...catch可以统一拦截它们在调试模式YII_DEBUG true下异常与致命错误会以详细的调用栈call stack和源码行的形式展示支持使用**专用的控制器动作controller action**来展示错误即errorAction机制支持多种错误响应格式HTML、JSON、RAW 等。从源码看yii\web\ErrorHandler继承自抽象基类yii\base\ErrorHandlerframework/base/ErrorHandler.phpWeb 端渲染逻辑实现在 framework/web/ErrorHandler.php 中控制台应用则使用yii\console\ErrorHandlerframework/console/ErrorHandler.php以纯文本方式渲染异常。启用与禁用错误处理器默认是启用的。如果你确实想关闭它可以在应用的入口脚本如web/index.php中把常量YII_ENABLE_ERROR_HANDLER定义为falsedefined(YII_ENABLE_ERROR_HANDLER) or define(YII_ENABLE_ERROR_HANDLER, false);框架在 framework/BaseYii.php 中兜底定义了该常量默认值为truedefined(YII_ENABLE_ERROR_HANDLER) or define(YII_ENABLE_ERROR_HANDLER, true);当该常量保持默认时应用启动流程会调用 framework/base/Application.php 中的registerErrorHandler()把配置好的errorHandler组件实例注册为 PHP 的异常处理器、错误处理器与关闭函数处理器register()方法见 framework/base/ErrorHandler.php。注意关闭该功能会导致 PHP 错误与异常失去统一出口生产环境通常不应这样做。使用错误处理器yii\web\ErrorHandler以应用组件参见 structure-application-components.md的形式注册组件名为errorHandler可通过Yii::$app-errorHandler访问。你可以在应用配置中像下面这样配置它return [ components [ errorHandler [ maxSourceLines 20, ], ], ];上述配置会让异常页面最多展示 20 行源码。需要指出的是源码中 framework/web/ErrorHandler.php 给出的默认值是 19 行$maxSourceLines 19另外还有一个maxTraceSourceLines 13用于控制调用栈中每一帧源码行的展示数量。下面是 Web 版错误处理器常用的可配置属性速查表属性默认值作用maxSourceLines19异常页面主错误位置展示的源码行数上限maxTraceSourceLines13调用栈中每个栈帧展示的源码行数上限errorActionnull无调用栈信息时执行的路由如site/errornull表示由错误处理器自行渲染errorViewyii/views/errorHandler/error.php无调用栈信息时使用的视图exceptionViewyii/views/errorHandler/exception.php含调用栈信息时使用的视图callStackItemViewyii/views/errorHandler/callStackItem.php渲染单个调用栈帧的视图previousExceptionViewyii/views/errorHandler/previousException.php渲染前置异常链的视图displayVars[_GET, _POST, _FILES, _COOKIE, _SESSION]调试页面上展示的 PHP 全局变量列表traceLine{html}调用栈文件行的 HTML 模板此外基类yii\base\ErrorHandler还提供两个值得了解的安全相关属性discardExistingOutput默认true展示错误前丢弃已输出的页面内容避免错误页面混入脏数据memoryReserveSize默认262144即 256KB预分配内存用于在内存耗尽out of memory时仍能渲染错误见 framework/base/ErrorHandler.php。非致命错误也是可捕获的异常正如前文所说错误处理器会把所有非致命 PHP 错误转换为可捕获的异常。这背后的实现是yii\base\ErrorHandler::handleError()framework/base/ErrorHandler.php当错误级别命中当前error_reporting()掩码时它构造一个yii\base\ErrorException并直接throw出去。因此你完全可以用下面的代码来“接住” PHP 错误use Yii; use yii\base\ErrorException; try { 10/0; } catch (ErrorException $e) { Yii::warning(Division by zero.); } // 程序继续执行...需要留意的边界在 PHP 7.4 之前__toString()内不允许抛出异常handleError()对__toString上下文做了特殊处理直接走handleException()并退出同时错误处理器会“手动”加载ErrorException类因为错误可能发生在自动加载本身失效的时刻。这些细节见 framework/base/ErrorHandler.php。抛出 HTTP 异常以呈现规范错误页如果你希望向用户展示“请求无效或异常”的错误页面直接抛出一个yii\web\HttpException即可例如yii\web\NotFoundHttpException。错误处理器会自动设置响应的 HTTP 状态码并使用合适的错误视图展示错误信息use yii\web\NotFoundHttpException; throw new NotFoundHttpException();yii\web\HttpExceptionframework/web/HttpException.php通过$statusCode属性携带标准 HTTP 状态码如 403、404、500并利用Response::$httpStatuses生成用户友好的异常名如 Not Found Exception。实践中常带状态码与消息if ($item null) { // item 不存在 throw new \yii\web\HttpException(404, The requested Item could not be found.); }错误记录日志行为每次异常被处理时基类还会调用logException()framework/base/ErrorHandler.php把异常写入日志普通异常按类名分类HttpException按yii\web\HttpException:{statusCode}分类ErrorException按类名:严重级别分类。这意味着你可以在日志中按状态码检索 404/500 等错误。自定义错误显示错误处理器会根据常量YII_DEBUG的值调整错误展示方式YII_DEBUG true调试模式展示带有详细调用栈和源码行的异常页面便于定位问题YII_DEBUG false只展示错误消息本身避免泄露应用敏感信息如文件路径、SQL 等。Info: 如果异常是yii\base\UserException的子类则无论YII_DEBUG取值如何都不会展示调用栈。因为这类异常被认为是由用户误操作引起的开发者无需修复任何东西。yii\web\HttpException正是UserException的子类所以 404 页面通常不会暴露调用栈。默认情况下错误处理器使用两个内置视图展示错误yii/views/errorHandler/error.php源码见 framework/views/errorHandler/error.php在不展示调用栈时使用。当YII_DEBUG false时这是唯一会展示的错误视图——一个简洁的白底页面仅包含错误名、消息、时间戳等并输出“An internal server error occurred.”之类的通用文案。yii/views/errorHandler/exception.php源码见 framework/views/errorHandler/exception.php在展示调用栈时使用。这是调试模式下的“豪华”页面包含异常类型链接、_GET/_POST/_SESSION等请求全局变量由displayVars控制、每个栈帧的可折叠源码块、复制栈信息按钮等。判断逻辑位于 framework/web/ErrorHandler.php当响应格式为 HTML 且!YII_DEBUG或异常为UserException时走errorView否则走exceptionView。你可以通过配置errorView与exceptionView属性换成自己的视图从而自定义错误展示。不过更推荐的做法是使用下面的errorAction机制。使用错误动作Error Actions自定义错误展示的更好方式是使用专用的错误动作action。首先在配置中把errorHandler组件的errorAction属性指向一个路由return [ components [ errorHandler [ errorAction site/error, ], ] ];errorAction接收一个动作路由。上面的配置表明当错误需要在不展示调用栈的情况下展示时执行site/error动作。从源码看framework/web/ErrorHandler.php此时错误处理器会清空视图、调用Yii::$app-runAction($this-errorAction)并把动作返回值作为响应数据。然后创建SiteController中的error动作namespace app\controllers; use Yii; use yii\web\Controller; class SiteController extends Controller { public function actions() { return [ error [ class yii\web\ErrorAction, ], ]; } }上面的代码使用yii\web\ErrorAction类framework/web/ErrorAction.php定义error动作它会渲染一个名为error的视图views/site/error.php。ErrorAction的关键行为包括init()中通过findException()从Yii::$app-errorHandler-exception获取当前异常如果错误动作被直接访问而没有异常上下文则自动抛出NotFoundHttpException(Page not found.)见 framework/web/ErrorAction.php避免误访问时出现空白页运行时会用setStatusCodeByException()同步响应状态码对 AJAX 请求直接返回错误名: 错误消息的纯文本对普通请求渲染 HTML 视图见 framework/web/ErrorAction.php对UserException用户输入类错误展示真实消息对其他异常则展示defaultMessage默认 An internal server error occurred.防止泄露内部细节见 framework/web/ErrorAction.php。除了使用ErrorAction类你也可以用普通动作方法定义error动作public function actionError() { $exception Yii::$app-errorHandler-exception; if ($exception ! null) { return $this-render(error, [exception $exception]); } }无论采用哪种方式都需要创建视图文件views/site/error.php。如果错误动作定义为yii\web\ErrorAction在该视图文件中你可以使用以下变量name错误名称message错误消息exception异常对象通过它可以获取更多有用信息例如 HTTP 状态码、错误码、错误调用栈等。Info: 如果使用基础项目模板或高级项目模板错误动作和错误视图通常已经定义好了基础模板的SiteController::actions()中就包含error动作视图为views/site/error.php。Note: 如果需要在错误处理器中进行重定向请采用下面的方式Yii::$app-getResponse()-redirect($url)-send(); return;在发送响应后立即return避免后续渲染继续执行。若动作方法返回了Response对象ErrorHandler也会直接把它作为响应结果见 framework/web/ErrorHandler.php。一个可直接落地的错误视图示例下面是views/site/error.php的典型实现同时兼容ErrorAction传入的name/message/exception变量?php /** var string $name 错误名称 */ /** var string $message 错误消息 */ /** var \Throwable $exception 异常对象 */ use yii\helpers\Html; $this-title $name; ? div classsite-error h1? Html::encode($name) ?/h1 div classalert alert-danger ? nl2br(Html::encode($message)) ? /div p 上述错误发生在 Web 服务器处理你的请求时。 如果你认为这是服务器错误请联系我们谢谢。 /p /div自定义错误响应格式错误处理器会根据 response 组件的格式设置来展示错误。如果yii\web\Response::format是html则使用前面提到的 error / exception 视图对于其他格式错误处理器会把异常的数组表示赋值给yii\web\Response::data属性再由响应组件按对应格式转换输出。数组表示由convertExceptionToArray()生成framework/web/ErrorHandler.php包含的字段随模式不同而增减基础字段name异常名、message异常消息、code错误码当异常为HttpException时追加statusHTTP 状态码YII_DEBUG true时追加type异常类名、file、line、stack-trace若为yii\db\Exception还追加error-infoUserException例外不输出栈信息存在前置异常时递归追加previous字段非调试模式下非UserException/HttpException的异常会被替换为通用的 500HttpException消息 An internal server error occurred.防止泄露内部细节。例如当响应格式为json时你会看到类似下面的响应HTTP/1.1 404 Not Found Date: Sun, 02 Mar 2014 05:31:43 GMT Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y Transfer-Encoding: chunked Content-Type: application/json; charsetUTF-8 { name: Not Found Exception, message: The requested resource was not found., code: 0, status: 404 }在 RESTful API 场景下前端通常期望统一包裹的错误结构。你可以通过响应response组件的beforeSend事件来定制错误响应格式在应用配置中注册事件处理器return [ // ... components [ response [ class yii\web\Response, on beforeSend function ($event) { $response $event-sender; if ($response-data ! null) { $response-data [ success $response-isSuccessful, data $response-data, ]; $response-statusCode 200; } }, ], ], ];上面的代码会把错误响应重排成如下格式注意这里把状态码强制改成了 200是否采纳取决于你的 API 约定——通常更推荐保留真实状态码并增加success标记HTTP/1.1 200 OK Date: Sun, 02 Mar 2014 05:31:43 GMT Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y Transfer-Encoding: chunked Content-Type: application/json; charsetUTF-8 { success: false, data: { name: Not Found Exception, message: The requested resource was not found., code: 0, status: 404 } }对于FORMAT_RAW格式错误处理器会直接把异常转换为字符串convertExceptionToString()非调试模式下统一返回 An internal server error occurred.适合纯文本接口。错误处理的内部流程速览综合以上源码一次典型的错误处理流程如下PHP 抛出错误或异常被yii\base\ErrorHandler::register()注册的处理器捕获set_exception_handler/set_error_handler/register_shutdown_function见 framework/base/ErrorHandler.phphandleException()记录当前异常、注销自身以避免递归、预置 500 状态码、写入日志并清空已输出内容见 framework/base/ErrorHandler.phpyii\web\ErrorHandler::renderException()根据响应格式与YII_DEBUG决定出口HTML 且配置了errorAction则运行动作HTML 无动作则渲染errorView或exceptionViewRAW 输出字符串其余格式输出数组见 framework/web/ErrorHandler.php响应组件最终把data按format序列化并发送给客户端致命错误fatal error由handleFatalError()在 shutdown 阶段兜底处理其渲染逻辑与普通异常一致见 framework/base/ErrorHandler.php。值得一提的是yii\console\ErrorHandlerframework/console/ErrorHandler.php对控制台应用如迁移、定时任务做了适配以纯文本输出异常类名、消息与栈帧并递归渲染前置异常便于在终端中阅读。常见问题与最佳实践生产环境务必YII_DEBUG false否则异常页会输出文件路径、源码与请求变量这是敏感信息泄露的主要来源之一。用户输入相关的校验失败用UserException子类既能展示给用户又不会泄露调用栈。业务层统一抛HttpException让错误处理器帮你设置状态码与响应格式而不是在控制器里手写http_response_code()。REST API 统一错误结构通过response组件的beforeSend事件包裹success/data字段或保留状态码 增加success标记让前端错误处理逻辑统一。错误日志联动logException()会自动按HttpException:{statusCode}分类记录配合 runtime-logging.md 中的日志配置可实现对 4xx/5xx 错误的监控与告警。延伸阅读运行时总览一次请求的完整生命周期响应组件与格式设置控制器与动作action、route视图的创建与渲染应用组件配置日志与监控核心实现源码framework/web/ErrorHandler.php、framework/base/ErrorHandler.php、framework/web/ErrorAction.php、framework/views/errorHandler/error.php【免费下载链接】yii2Yii 2: The Fast, Secure and Professional PHP Framework项目地址: https://gitcode.com/gh_mirrors/yi/yii2创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

前端实战:滚动监听实现顶部 logo 平滑显隐效果

前端实战:滚动监听实现顶部 logo 平滑显隐效果

开发弹窗、侧边抽屉、全屏遮罩这类组件时,经常会遇到一个问题:弹窗弹出后,底层页面依然可以滚动,体验很差。常见方案就是控制 body 的滚动,本文使用 jQuery 实现禁止页面滑动和恢复页面滑动,同时说明坑点。…

2026/9/24 17:03:13 阅读更多 →
Visdom 窗口系统完全指南:Window ID、拖拽布局、程序化操作与实时参数编辑

Visdom 窗口系统完全指南:Window ID、拖拽布局、程序化操作与实时参数编辑

Visdom 窗口系统完全指南:Window ID、拖拽布局、程序化操作与实时参数编辑 【免费下载链接】visdom Tool for real-time visualization, monitoring and collaborative analysis of AI/ML experiments and live data. Supports Python, PyTorch/Torch, NumPy, Tenso…

2026/9/24 17:03:13 阅读更多 →
第23篇-将你的Server发布到MCP-Registry

第23篇-将你的Server发布到MCP-Registry

【MCP 全栈教程】第 23 篇:将你的 Server 发布到 MCP Registry 本系列定位:从协议原理到 Server 开发、Client 开发、再到各大平台实战集成,系统化掌握 MCP(Model Context Protocol)全栈技术体系。 本篇你将学到 serv…

2026/9/24 17:02:13 阅读更多 →

最新新闻

Win10 文件内容搜索全攻略:从索引开启到命令行实战

Win10 文件内容搜索全攻略:从索引开启到命令行实战

你肯定遇到过这种事:文件叫"未命名文档",或者某次随手存了个"111"命名的 Word,隔了三个月只记得里面写过"项目预算"四个字,在 Win10 里用搜索框一搜,结果空空如也。绝大多数人以为 Win1…

2026/9/24 23:23:14 阅读更多 →
.NET 8快速开发框架实践:拒绝过度设计,开箱即用

.NET 8快速开发框架实践:拒绝过度设计,开箱即用

这些年我带团队做企业级项目,最深的感受是:真正拖垮开发进度的往往不是业务本身复杂,而是框架太重。一个新项目刚起步,光搭环境、配权限、折腾ORM和依赖注入就能耗掉两三天,等真正开始写业务代码,激情已经消…

2026/9/24 23:23:14 阅读更多 →
用Dify和LangBot打造多平台群聊AI写作助手:从部署到实战

用Dify和LangBot打造多平台群聊AI写作助手:从部署到实战

做内容的人应该都有过这种经历:在群里被连环,一会儿有人丢来一沓会议记录让提炼摘要,一会儿又是宣传文案让换个开头,一会儿是产品说明太长问有没有精简版。你切到AI网页端提问,再把结果复制回群里,上下文长…

2026/9/24 23:23:14 阅读更多 →
绳子检测数据集VOC/YOLO格式解析与YOLOv8训练实战全流程

绳子检测数据集VOC/YOLO格式解析与YOLOv8训练实战全流程

简介:这是一份用于目标检测训练的标准绳子检测数据集,已按Pascal VOC和YOLO两种主流格式整理,适合计算机视觉初学者、算法工程师及需要绳索识别能力的物流安防、工业自动化项目直接使用。压缩包共968个文件,由jpg原图、VOC格式xml…

2026/9/24 23:23:14 阅读更多 →
.NET快速开发框架实践:拒绝过度设计,开箱即用

.NET快速开发框架实践:拒绝过度设计,开箱即用

.NET 生态里不缺框架,缺的是那种让你拿来就能干活、不用先读三天文档的框架。我自己经历过好几轮从零搭架构的痛苦,也接手过那种“配置比业务代码还多”的重型项目,所以看到“拒绝过度设计”这几个字的时候,我是真的挺有感触。我理…

2026/9/24 23:23:14 阅读更多 →
STM32开发调试经验总结:从环境搭建到外设细节的避坑指南

STM32开发调试经验总结:从环境搭建到外设细节的避坑指南

接手STM32项目这些年,我自己踩过不少坑,也帮别人填过不少坑。回头看看,真正难的不是芯片本身,而是那些“看起来是软件问题,根子却在硬件/环境/配置上”的阴沟。这篇文章算是一次阶段性的STM32开发调试经验总结&#xf…

2026/9/24 23:22:13 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →