hyperf需组合配置php错误报告、日志通道和异常处理器三处才能开启全局错误输出:启用error_reporting(e_all)和display_errors;配置logger.php的error级别日志通道;在exceptions.php中注册异常处理器捕获并记录未捕获异常。

Hyperf 默认不会把 PHP 错误(如 Notice、Warning、未捕获异常)直接输出到终端或日志,尤其在生产环境会静默忽略。要开启全局错误输出,关键不是改一个开关,而是组合调整 PHP 运行时配置 + Hyperf 日志通道 + 异常处理器三处,让错误“看得见、留得下、分得清”。
启用 PHP 错误报告并输出到 STDERR
Hyperf 启动后运行在 Swoole 协程中,PHP 的 error_reporting 和 display_errors 设置仍生效,但需确保它们在进程启动前就已生效:
- 在
php.ini中设置:error_reporting = E_ALL、display_errors = On(仅开发环境启用,生产禁用) - 更推荐方式:在项目入口或
config/autoload/bootstrap.php中强制开启:error_reporting(E_ALL); ini_set('display_errors', '1'); - 注意:Swoole 的
display_errors不影响 CLI 输出,但会影响var_dump、echo等是否出现在 Supervisor 的 stdout_logfile 中——前提是 Hyperf 没启用--daemonize(这点必须确认)
配置 logger.php 让错误进文件
光靠 PHP 原生报错不够,真正落地的日志要走 Hyperf 的日志系统。修改 config/autoload/logger.php,确保 default channel 能记录 ERROR 及以上级别:
- 检查
level配置不小于Monolog\Logger::ERROR(如设为DEBUG则所有级别都记) - handler 使用
StreamHandler或RotatingFileHandler,路径指向可写的runtime/logs/目录(例如:BASE_PATH . '/runtime/logs/error.log') - 避免多个 handler 写进同一个 channel;如需单独存错误日志,定义新 channel(如
'error'),并在异常处理器中显式调用
注册全局异常处理器捕获未处理异常
PHP 错误(E_ERROR 类)和未捕获异常(Throwable)需由 Hyperf 的异常机制兜底:
- 在
config/autoload/exceptions.php中注册自定义异常处理器类 - 该类实现
RequestExceptionHandlerInterface,在handle()方法中主动写日志:$this->logger->error('Uncaught exception', ['exception' => $throwable]); - 确保该处理器的
isValid()返回true或精准匹配异常类型,否则会被跳过
验证是否生效的快速方法
改完别急着上线,本地先验证:
- 在任意控制器里写一行触发 Notice:
echo $undefined_var;,看终端或runtime/logs/下是否有对应记录 - 抛出异常:
throw new RuntimeException('test error');,检查日志是否包含堆栈和上下文 - 若用 Supervisor 管理,确认其
stdout_logfile和stderr_logfile路径有内容,且不是空文件(说明没被重定向丢弃)











