# PHP7+ 异常改进:Throwable 接口与错误异常化
PHP7 带来了许多重大改进,其中异常处理机制的革新尤为突出。本文将深入解析 PHP7+ 中的 Throwable 接口以及错误异常化机制,帮助你掌握现代 PHP 异常处理的最佳实践。
## 一、PHP7 之前的异常处理局限
在 PHP7 之前,PHP的错误处理机制存在明显缺陷:
- 致命错误无法被捕获(如内存溢出、语法错误等)
- 错误和异常两套独立机制,处理方式不统一
- 自定义错误处理函数(set_error_handler)无法处理所有错误类型
```php
// PHP5 示例:无法捕获致命错误
try {
    callNoneExistFunction(); // 致命错误:函数不存在
} catch (Exception $e) {
    // 永远不会执行到这里
    echo "Caught exception: ".$e->getMessage();
}
```
## 二、Throwable 接口:统一错误与异常
PHP7 引入了 Throwable 接口作为所有可抛出对象的基接口:
```
Throwable
├── Error
│   ├── TypeError
│   ├── ParseError
│   ├── ArithmeticError
│   │   └── DivisionByZeroError
│   └── AssertionError
└── Exception
    └── ... (所有用户自定义异常)
```
这种结构带来两大改进:
1. Error 和 Exception 现在共享同一个接口
2. 致命错误现在可以被捕获为 Error 对象
```php
try {
    callNoneExistFunction(); // 现在会抛出 Error
} catch (Throwable $e) {
    // 现在可以捕获 Error 了
    echo "Caught: ".$e->getMessage();
}
```
## 三、错误异常化实战
### 1. 捕获解析错误(ParseError)
```php
try {
    eval("invalid php code"); // 产生 ParseError
} catch (ParseError $e) {
    echo "Parse error: ".$e->getMessage();
}
```
### 2. 类型错误处理(TypeError)
```php
function add(int $a, int $b): int {
    return $a + $b;
}
try {
    echo add("not a number", 2); // 抛出 TypeError
} catch (TypeError $e) {
    echo "Type error: ".$e->getMessage();
}
```
### 3. 算术错误处理(DivisionByZeroError)
```php
try {
    $result = 1 / 0; // 抛出 DivisionByZeroError
} catch (DivisionByZeroError $e) {
    echo "Cannot divide by zero";
}
```
## 四、最佳实践建议
1. **捕获 Throwable 而非 Exception**:
   ```php
   try {
       // 可能抛出 Error 或 Exception 的代码
   } catch (Throwable $e) {
       // 处理所有可抛出对象
   }
   ```
2. **特定错误优先处理**:
   ```php
   try {
       // 业务代码
   } catch (DivisionByZeroError $e) {
       // 专门处理除以零
   } catch (TypeError $e) {
       // 专门处理类型错误
   } catch (Throwable $e) {
       // 通用错误处理
   }
   ```
3. **错误转化为异常**(兼容旧代码):
   ```php
   set_error_handler(function($errno, $errstr) {
       throw new ErrorException($errstr, $errno, $errno);
   });
   ```
4. **finally 块的妙用**:
   ```php
   $resource = acquireResource();
   try {
       useResource($resource);
   } catch (Throwable $e) {
       logError($e);
   } finally {
       releaseResource($resource); // 确保资源释放
   }
   ```
## 五、性能考量
PHP7 的异常处理经过优化:
- 异常抛出和捕获的性能开销大幅降低
- 错误异常化不会带来额外性能负担
- 相比于传统错误处理,异常机制在错误情况下性能更好
## 结语
PHP7+ 的异常改进使 PHP 的错误处理更加现代化和统一。掌握 Throwable 接口和错误异常化机制,可以让你写出更健壮、更安全的 PHP 应用程序。建议在新建项目中全面采用新的异常处理机制,对于老项目可以逐步迁移。