<?php练功房

第 4 章 · 面向对象 · 第 4.4 课

错误与异常处理

约 15 分钟

程序总会遇到意外:用户输入了非法数据、文件不存在、数据库连不上。异常(Exception)是报告“这件事做不下去了”的标准方式:

  • throw new Exception("说明") 抛出异常,当前函数立刻停止执行。
  • 异常会一层层往上传,直到被 try { } catch (异常类型 $e) { } 接住。
  • finally 里的代码不管有没有异常都会执行,适合做收尾工作。
  • 没人接住的异常会让整个程序中止,并报 Uncaught ... 错误。

自定义异常

继承 Exception 就能定义自己的异常类型,还可以附带额外的数据。catch 按类型匹配,所以调用方可以针对不同的问题做不同的处理。PHP 内置了一批常用类型:InvalidArgumentException(参数不对)、RangeException(超出范围)、RuntimeException(运行时问题)等。

Error:PHP 自己抛出的错误

PHP 8 里,很多严重错误(调用不存在的函数、类型不对、除以 0)也会以 Error 的形式抛出,同样可以被 catch。Exception 和 Error 都实现了 Throwable 接口,catch (Throwable $e) 能接住所有东西,但一般只在最外层这样兜底。

选择题

finally 块什么时候执行?

练习 1

校验年龄

写函数 parseAge(string $input): int,把用户输入的字符串转成年龄:

  • 不是数字(用 is_numeric 判断):抛出 InvalidArgumentException,消息是 不是数字
  • 小于 0 或大于 150:抛出 RangeException,消息是 年龄超出范围(负数也是数字,只是超出范围)
  • 否则返回整数年龄

练习 2

安全地批量处理

$inputs 里有好几个待处理的年龄,其中有非法数据。用上一题的 parseAge(已经写好了)逐个处理:合法的输出年龄,非法的输出错误消息,一个出错不能影响后面的。期望输出:

18
不是数字
年龄超出范围
42