php怎么处理异常错误_php try catch捕获异常教程【稳健】

12次阅读

php try catch 默认无法捕获 notice 和 warning,因其属于错误机制而非异常体系;需用 set_error_handler 转为 errorexception 才能捕获;pdo 异常须显式启用 errmode_exception;自定义异常应继承 exception;finally 中 return 会覆盖 catch 返回值。

php 怎么处理异常错误_php try catch 捕获异常教程【稳健】

PHP try catch 捕获不到 Notice 和 Warning?

默认情况下,try catch 只捕获 Exception 及其子类(比如 RuntimeException),而 E_NOTICEE_WARNING 这类错误是 PHP 错误机制的一部分,不属于异常体系。

常见现象:代码里写了 try {echo $undefined_var;} catch (Exception $e) {},但页面照样报 Notice: Undefined variable,且没进 catch 块。

  • 想统一处理所有错误类型,得用 set_error_handler() 配合手动抛出异常
  • 注意:不能在 set_error_handler 里直接 throw,因为部分错误(如 E_ERROR)会绕过它;稳妥做法是把 E_NOTICE/E_WARNING 转成 ErrorException 再 throw
  • error_reporting(E_ALL) 要提前设置,否则低级别错误可能被静默忽略
set_error_handler(function($severity, $message, $file, $line) {if (!(error_reporting() & $severity)) return;     throw new ErrorException($message, 0, $severity, $file, $line); });

捕获 PDO 数据库异常必须开启异常模式

很多人写了 try {$pdo->query("SELECT * FROM nonexist"); } catch (PDOException $e) {} 却没生效——根本原因是 PDO 默认不抛异常,而是返回 false 并触发警告。

  • 连接时必须显式设置 PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
  • 只设连接选项不够,如果用 PDOStatement 执行查询,异常仍来自该对象,但前提是连接层已启用异常模式
  • 别漏掉 PDO::ATTR_EMULATE_PREPARES => false,否则某些 SQL 错误(如语法错)可能被模拟层吞掉,不触发异常
$pdo = new PDO($dsn, $user, $pass, [     PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,     PDO::ATTR_EMULATE_PREPARES => false]);

自定义异常类要继承 Exception 或 Throwable

PHP 7+ 支持 Throwable,但直接 class MyError extends Throwable 是非法的——Throwable 是接口,不能被继承,只能实现,而实际可用的基类只有 ExceptionError

立即学习 PHP 免费学习笔记(深入)”;

  • 业务异常建议继承 Exception,比如 class ValidationException extends Exception
  • 如果需要区分“程序错误”和“业务错误”,可约定用不同类名,但不要试图继承 Error(它是 PHP 内部错误专用,用户代码 throw 它会被拒绝)
  • 构造时传参顺序固定:__construct($message, $code = 0, Throwable $previous = null),别漏掉第三个参数,否则链式异常(比如捕获后重抛)会断掉上下文

finally 中 return 会覆盖 catch 里的 return

这是最容易踩的逻辑坑:你以为 catch 返回了错误信息,结果前端收到的是 finally 里的值。

  • finally 块只要执行了 return,就一定会覆盖 trycatch 中的 return
  • 即使 catch 抛出了新异常,finally 里的 return 也会压制它(PHP 7.1+ 会报 Uncaught Throwable 警告)
  • 安全做法:在 finally 里只做清理(关文件、释放锁),绝对不要 returnthrow
function risky() {     try {         throw new Exception('boom');     } catch (Exception $e) {return 'handled';} finally {return 'ignored? no — this wins'; // ← 实际返回这个} }

异常处理真正的复杂点不在语法,而在错误分类和传播路径的设计。比如数据库超时该转成 ServiceUnavailableException 还是重试?日志里要不要保留原始堆栈?这些没法靠 try catch 自动解决。

text=ZqhQzanResources