PHP7中未捕获异常无法写入error_log的原因及解决方案
聊聊PHP7中error_reporting(0)和未捕获异常日志的那点事
1. error_reporting(0)会抑制异常吗?
其实准确来说,它不会直接阻止异常抛出——你的代码里异常确实抛出来了,但它会间接让PHP默认的日志机制不记录这个未捕获异常。
PHP处理未捕获异常时,会检查当前的error_reporting级别是否包含E_ERROR(未捕获异常属于这个级别范畴),当你设成error_reporting(0),等于关掉了所有错误类型的报告开关,默认的日志写入流程自然就被跳过了,所以你看不到error_log生成。
2. 怎么在开着error_reporting(0)的同时,只记录未捕获异常?
核心思路是绕开默认的错误报告限制,自己接管未捕获异常的处理逻辑。用set_exception_handler注册一个自定义异常处理器就行,具体代码如下:
<?php // 关掉常规错误的报告 error_reporting(0); // 开启错误日志功能 ini_set('log_errors', 1); // 注册自定义的未捕获异常处理器 set_exception_handler(function (Throwable $e) { // 整理异常的详细信息,包括追踪栈 $logContent = sprintf( "[%s] Uncaught Exception: %s\nFile: %s Line: %s\nStack Trace:\n%s\n", date('Y-m-d H:i:s'), $e->getMessage(), $e->getFile(), $e->getLine(), $e->getTraceAsString() ); // 写入error_log,这里用3表示追加到指定日志文件(没指定就用PHP默认的) error_log($logContent, 3, ini_get('error_log')); // 保持PHP默认的异常终止行为,退出程序 exit(1); }); // 测试抛出异常 throw new Exception('some exception here');
几个关键细节:
set_exception_handler会接管所有没被try/catch抓住的异常,完全不受error_reporting的级别限制- 你可以在处理器里自定义日志格式,比如加上时间戳,后续排查问题会更方便
- PHP7及以后版本,
Throwable是所有异常和错误的基类,用它能捕获到包括Error在内的所有未捕获的可抛出类型
这样设置后,普通的警告、通知类错误会被error_reporting(0)压下去,不会进入日志,但未捕获的异常会被稳稳记录到error_log里。
内容的提问来源于stack exchange,提问作者779IDEAS
相关产品推荐
相关产品推荐

