php错误类型有明确分级:e_warning(运行时警告,脚本继续)、e_error(致命错误,立即终止)、e_notice(未定义变量等隐患)、e_deprecated(弃用功能)、e_parse(语法错误,无法解析);set_error_handler仅捕获非致命错误,需提前注册并返回true,而fopen等函数抛出的是错误而非异常,须配合errorexception转换才能被try-catch捕获。

别从“教程”开始学 PHP 错误处理——先搞清你当前卡在哪一环,再针对性补漏。
看不懂错误信息里那串 E_WARNING、E_NOTICE 是啥意思
PHP 的错误类型不是随便命名的,每个常量对应明确的严重程度和行为。比如 E_WARNING 表示运行时出问题(如 include 了一个不存在的文件),脚本不会停,但得留意;而 E_ERROR 一出现就中断执行,比如调用未定义函数。
-
E_NOTICE:访问未定义变量、使用未初始化数组键 —— 不报错也能跑,但大概率是逻辑隐患 -
E_DEPRECATED:用了即将被删的功能(如mysql_connect),PHP 8 已彻底移除 -
E_PARSE:语法错误,根本解析不过去,set_error_handler捕不到,只能靠 IDE 或 CLI 报错定位
开发时建议在入口加一句:error_reporting(E_ALL & ~E_DEPRECATED);,既不漏问题,又过滤掉干扰项。
set_error_handler 注册了却没生效
最常见原因是注册太晚,或错误类型压根不归它管。它只捕获非致命错误(E_WARNING、E_NOTICE、E_USER_* 等),对 E_ERROR、E_PARSE、E_CORE_ERROR 完全无效。
- 必须在错误发生前注册,比如放在
index.php最开头,别等路由加载完才设 - 返回值必须是
true,否则 PHP 会继续走默认流程,导致日志写了两遍、页面还弹警告 - 若想统一处理所有错误,得配合
register_shutdown_function+error_get_last()补漏致命错误
示例中容易漏掉这一行:return true;,不写就等于没接管。
为什么 try-catch 捕不到 fopen 失败
因为 fopen 抛的是传统错误(E_WARNING),不是异常。PHP 默认不把错误转成异常,除非你主动干预。
- PDO 可以通过
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION)开启异常模式,但普通函数不行 - 想让
fopen也进catch,得先用set_error_handler捕获E_WARNING,再在处理器里throw new ErrorException($errstr, $errno, 0, $errfile, $errline) - 注意:
ErrorException是Exception的子类,能被通用catch (Exception $e)捕获,但不能被catch (Error $e)捕获(那是给 PHP 7+ 内置Error类用的)
生产环境日志写到哪、怎么不暴露给用户
核心就两条:关显示、开记录,且路径得可控。
- 禁用前端输出:
ini_set('display_errors', '0');,别依赖 php.ini,有些共享主机不允许改 - 启用错误日志:
ini_set('log_errors', '1');,并指定位置:ini_set('error_log', '/var/log/myapp/php-error.log'); - 确保 Web 进程有写权限,且目录不在 Web 根目录下(避免被直接下载)
- 如果用
error_log()函数手动写,注意第四个参数设为3(追加写入),否则每次覆盖
真正容易被忽略的是:不同 SAPI(CLI / FPM / Apache 模块)可能读取不同的 php.ini,phpinfo() 查 Loaded Configuration File 才算数,光看本地配置文件没用。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











