php的try-catch捕不到notice和warning,因其属错误级别而非异常;需用set_error_handler()拦截并手动throw;php 7+中error可被catch(throwable $e)捕获,但parse error不行;finally中return会覆盖异常,应仅用于清理。

try-catch 捕不到 Notice 和 Warning?
PHP 的 try-catch 默认只捕获继承自 Throwable 的异常(比如 Exception、Error),而 E_NOTICE、E_WARNING 这类错误属于“错误级别”,不是异常,直接绕过 try-catch 流程。
常见错误现象:try { echo $undefined_var; } catch (Exception $e) { } —— 完全没用,照样报 Notice 并继续执行。
- 要用
set_error_handler()拦截E_NOTICE/E_WARNING,再手动 throw 新异常 -
error_reporting(E_ALL)不影响try-catch范围,它只控制是否显示/记录错误 - PHP 7+ 中
Error类已实现Throwable,所以Fatal Error(如调用不存在的函数)可被catch (Throwable $e)捕获,但Parse Error仍不行——它发生在编译期,根本进不了运行时
catch (Exception $e) 和 catch (Throwable $e) 该选哪个?
PHP 7 引入了 Throwable 接口,统一了 Exception 和 Error 的处理入口。只写 catch (Exception $e) 会漏掉 Error(比如 TypeError、ParseError 的子类)。
使用场景:你希望统一兜底所有运行时崩溃点,比如框架顶层异常处理器。
立即学习“PHP免费学习笔记(深入)”;
- 兼容 PHP 5 和 7?只能用
catch (Exception $e),但 PHP 5 下Error根本不存在 - 只跑 PHP 7.0+?优先用
catch (Throwable $e),更安全 - 别写
catch (Exception $e) catch (Error $e)—— PHP 不支持多类型并列 catch(除非用多个独立catch块,但顺序必须是子类在前、父类在后)
finally 里 return 会吞掉 throw?
会。只要 finally 块里有 return,无论 try 或 catch 中抛出什么异常,都会被静默丢弃,函数直接返回 finally 的值。
常见错误现象:
function test() {
try {
throw new Exception('boom');
} finally {
return 'done';
}
}
echo test(); // 输出 'done',异常消失了-
finally应只做清理(关文件、释放资源),避免return或throw - 如果真要干预流程,用
if (isset($e)) { /* 处理异常 */ }配合外部变量,而不是靠return - PHP 7.1+ 允许
finally中throw,但它会覆盖前面的异常 —— 这不是 bug,是规范行为
自定义异常要不要 extends Exception?
要,但必须注意继承链。PHP 要求所有异常类最终实现 Throwable,而 Exception 是最常用基类。
参数差异和兼容性影响:
- 不继承任何类 → 无法被
catch (Exception $e)捕获(PHP 7+ 可能报致命错误) - 继承
Exception→ 兼容所有 PHP 版本,推荐做法 - 继承
Error→ 错误!Error是系统级错误,用户不应创建其实例 - 构造函数参数保持和
Exception一致:__construct($message = '', $code = 0, Throwable $previous = null),否则 IDE 提示和框架集成可能出问题
复杂点在于:异常类本身如果触发错误(比如构造时访问了未定义属性),会导致二次崩溃,且难以调试。所以自定义异常里尽量避免逻辑,只存数据。









