PHP 7+ 支持多 catch 块,需按子类到父类顺序书写,否则子类异常被父类提前捕获;PHP 8.0+ 支持联合类型如 InvalidArgumentException|DomainException;PHP 5.x 仅支持单 catch,须用 instanceof 手动分支处理。

PHP 7+ 怎么写多个 catch 块
PHP 7 开始支持真正意义上的多类型 catch,不是靠 if 判断异常类名,而是语法原生支持。关键点:每个 catch 必须明确指定一个异常类(或其父类),且顺序很重要——子类必须写在父类前面,否则会被父类提前捕获。
- 错误写法:
catch (Exception $e)写在最前,后面再写catch (InvalidArgumentException $e)→ 后者永远进不去 - 正确顺序:先
catch (InvalidArgumentException $e),再catch (RuntimeException $e),最后兜底catch (Exception $e) - PHP 8.0+ 支持联合类型写法:
catch (InvalidArgumentException|DomainException $e),但注意这只能用于同级、无继承关系的类,且不能混用变量解构
为什么 catch 顺序错会导致异常“消失”
PHP 的 catch 是从上到下线性匹配的,一旦某个 catch 的类型声明能接受当前异常实例(即 instanceof 为 true),就立刻进入该块,后续 catch 完全不执行。这不是静默失败,是设计如此。
- 典型现象:抛出
LogicException,但只进了catch (Exception $e),没进更具体的catch (LogicException $e)→ 八成是后者位置靠后 -
Throwable是所有异常和错误的根接口,放在最前会吞掉一切,包括Error(如ParseError、FatalError) - 调试建议:临时加
var_dump(get_class($e));确认实际抛出的类名,再核对catch顺序
PHP 5.x 没有多个 catch 怎么办
PHP 5.x 只允许一个 catch,必须手动判断异常类型。这不是“模拟”,而是唯一可行路径,别试图用反射或字符串匹配绕过。
- 用
get_class()或instanceof分支处理:try { // ... } catch (Exception $e) { if ($e instanceof InvalidArgumentException) { // 处理 } elseif ($e instanceof RuntimeException) { // 处理 } else { throw $e; // 不认识的异常,重新抛出或记录 } } - 避免用
strpos(get_class($e), 'Exception')这类字符串判断——类名可能含命名空间,且易误判(比如MyCustomException匹配到Exception) - 如果项目已升级到 PHP 7+,别再沿用 PHP 5 的写法,语法糖不是装饰,是减少出错概率的实质改进
容易被忽略的 catch 兼容性细节
有些异常类型在不同 PHP 版本中行为不一致,光看 catch 语法还不够。
-
Error类型(如TypeError、ParseError)在 PHP 7+ 才实现Throwable接口,PHP 5 下根本捕获不到,会直接 fatal -
set_exception_handler()无法捕获Error,必须用set_error_handler()+register_shutdown_function()配合检测error_get_last() - 自定义异常类必须继承
Exception或Throwable(PHP 7+),否则catch无效;PHP 5 中继承Exception是硬性要求
实际写的时候,最常卡住的不是语法,是没意识到 catch 顺序本质是类型匹配的优先级规则,而异常类的继承关系又常常被忽略。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











