PHP异常处理机制
异常处理主要由try、catch、finally三个关键字来实现。文中所有代码在PHP7环境下一切正常,PHP5及以下版本,部分代码并不能达到预期效果。废话少说,进入正题。
抛出、捕获异常
throw new Exception('异常信息');
执行上面的代码,输出如下
Fatal error: Uncaught Exception: 异常信息 in D:\WWW\demo\index.php:2 Stack trace: #0 {main} thrown in D:\WWW\demo\index.php on line 2
捕获这个异常
try {
throw new Exception('异常信息', 1);
} catch (Exception $e) {
print_r($e);
}
这是一个典型的异常捕获,打印Exception对象$e
Exception Object
(
[message:protected] => 异常信息
[string:Exception:private] =>
[code:protected] => 1
[file:protected] => D:\WWW\demo\index.php
[line:protected] => 3
[trace:Exception:private] => Array
(
)
[previous:Exception:private] =>
)
可以看到,这里包含了异常的详细信息。我们可以针对这个异常在catch代码块里进行下一步处理,比如让信息重新排版显示
try {
throw new Exception('异常信息', 1);
} catch (Exception $e) {
echo '信息:' . $e->getMessage() . "\r\n";
echo '位置:' . $e->getFile() . "\r\n";
echo '行:' . $e->getLine() . "\r\n";
echo 'code:' . $e->getCode();
}
再次执行上面代码,结果如下
信息:异常信息
位置:D:\WWW\demo\index.php
行:3
code:1
自定义异常类
新建两个自定义异常类MyException、DemoException,并且都继承自Exception基类,分别都定义一个handler方法用来处理异常信息。
MyException
namespace exception;
class MyException extends \Exception {
public function handler() {
echo '信息:' . $this->getMessage() . "\r\n";
echo '位置:' . $this->getFile() . "\r\n";
echo '行:' . $this->getLine() . "\r\n";
echo 'code:' . $this->getCode();
}
}
DemoException
namespace exception;
class DemoException extends \Exception {
public function handler() {
echo '我是DemoException异常,信息:' . $this->getMessage();
}
}
改造代码
use exception\MyException;
use exception\DemoException;
require 'exception/MyException.php';
require 'exception/DemoException.php';
try {
throw new DemoException('异常信息', 1);
} catch (MyException $e) {
$e->handler();
} catch (DemoException $e) {
$e->handler();
} catch (Exception $e) {
echo $e->getMessage();
}
执行上面代码,结果如下
我是DemoException异常,信息:异常信息
因此,在这里得出一个结论
在捕获异常时,会根据具体的异常类型去执行catch代码块,如果没有找到到对应的类型,则会视为Exception异常进行处理。
set_exception_handle函数
关于set_exception_handle函数,部分手册原文
set_exception_handler — 设置用户自定义的异常处理函数,用于没有用 try/catch 块来捕获的异常。
callable set_exception_handler ( callable $exception_handler )
手册中提到,set_exception_handle函数用于处理没有用try/catch块捕获的异常。抛出一个异常,不捕获
function MyException($e) {
echo '信息:' . $e->getMessage() . "\r\n";
echo '位置:' . $e->getFile() . "\r\n";
echo '行:' . $e->getLine() . "\r\n";
echo 'code:' . $e->getCode();
}
set_exception_handler('MyException');
throw new Exception('异常信息', 1);
执行上面的代码,结果如下
信息:异常信息
位置:D:\WWW\demo\index.php
行:9
code:1
这个异常已经由MyException处理,与之前捕获到的信息相同。当然了,set_exception_handler函数的参数为callable类型,所以也支持出入匿名函数、类方法。对MyException类稍加改动
namespace exception;
class MyException extends \Exception {
public function handler($e) {
echo '信息:' . $e->getMessage() . "\r\n";
echo '位置:' . $e->getFile() . "\r\n";
echo '行:' . $e->getLine() . "\r\n";
echo 'code:' . $e->getCode();
}
}
然后设置自定义异常处理也是可行的
set_exception_handler([(new MyException()), 'handler']);
finally
finally代码块不管程序有没有出现异常都会执行。
try {
throw new Exception('异常信息', 1);
} catch (Exception $e) {
print_r($e);
} finally {
echo 'Hello';
}
这种情况下,try代码块中不管有没有出现异常,Hello都会被输出。finally代码块中的代码总是被执行。