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

1次阅读

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