# Throwable 接口

## 目录：

* 简介
* Throwable 层次结构
* Error 对象

## 简介：

PHP7提供了一种全局的接口，使得所有的类都可以基于此使用throw关键字。在PHP中，异常与错误经常会遇到。**在PHP之前，异常可以被捕获，但是错误是不能被捕获的。从PHP7开始，任何完整程序或一部分程序中的Fatal错误都可以被捕获。**

> 为了更好的捕获诸多错误（大多数的 Fatal 错误），PHP7 提供了 throwable 接口，异常与错误都继承于这个接口。
>
> 注意：wom自己写的PHP类是不能直接继承throwable 接口的，如果希望继承throwable 接口，需要继承某个异常类。

PHP 7 改变了大多数错误的报告方式。不同于传统（PHP 5）的错误报告机制，现在大多数错误被作为 **Error** 异常抛出。

## Throwable层次结构：

* Throwable
  * Error
    * ArithmeticError
    * DivisionByZeroError
    * AssertionError
    * ParseError
    * TypeError
  * Exception
    * ...

## Error 对象：

现在大多数的Fatal错误情况会抛出一个Error实例，类似于异常捕获，Error实例可以被try/catch捕获，如下代码：

```php
<?php
function iHaveError($object)
{
    return $object->iDontExist();
}

iHaveError(null);

echo "I am still running";
```

以上代码会产生一个Fatal 的错误，程序也停止运行，并且最后一行的echo语句不会被执行。

现在加入try/catch 后，代码如下：

```php
<?php
function iHaveError($object)
{
    return $object->iDontExist();
}

try {
    iHaveError(null);
} catch(Error $e) {
    echo $e->getMessage();
}

echo "<br>I am still running";
```

再次执行以上代码，catch中的内容将会执行。并且代码会继续执行，最后的一行echo也会被输出。结果如下:

```
Call to a member function iDontExist() on null
I am still running
```

## DivisionByZeroError 对象(Error的子实例)

大多数情况下，Error实例会在大部分 Fatal 错误的情况下被抛出，但是对于一些错误情况，只有Error的子实例（见Error层次图）会被抛出,当然使用 Error 对象也是可以的。

如下代码：

```php
<?php
try {
    $a = 20;
    $division = $a % 0;
} catch(DivisionByZeroError $e) { // catch(Error $e) {
    echo $e->getMessage();
}
```

在PHP7之前，上面的代码会触发一个warning级别的错误，如今在PHP7中，执行上面的代码会抛出一个可以被捕获的DivisionByZeroError异常.如下:

```
Modulo by zero
```

补充:**除以零的变化**

```php
<?php
var_dump(3/0);
var_dump(0/0);
var_dump(0%0);
?>
```

Output of the above example in PHP 5:

```
Warning: Division by zero in %s on line %d
bool(false)

Warning: Division by zero in %s on line %d
bool(false)

Warning: Division by zero in %s on line %d
bool(false)
```

Output of the above example in PHP 7:

```
Warning: Division by zero in %s on line %d
float(INF)

Warning: Division by zero in %s on line %d
float(NAN)

PHP Fatal error:  Uncaught DivisionByZeroError: Modulo by zero in %s line %d
```

## ParseError 对象(Error的子实例)

> [eval函数](http://php.net/manual/zh/function.eval.php) — 把字符串作为PHP代码执行

当使用eval函数进行对字符串进行解析时,发生 Fatal 错误,如下

```
Parse error: syntax error, unexpected end of file in ....
```

如今在PHP7中，执行下面的代码会抛出一个可以被捕获的ParseError异常.如下:

```php
<?php
try {
    $command = 20;
    $b = eval($command);
} catch (ParseError $e) {
    echo $e->getMessage();
}
```

捕获到的异常如下:

```
syntax error, unexpected end of file
```

## 资料：

[PHP 7 错误处理](http://php.net/manual/zh/language.errors.php7.php)
