异常与错误的区别
关于异常处理这一块,在官方的手册上介绍的不够详细,所以我在这里再做一个相对详细一点的总结。
首先要明白异常跟错误是两个不一样的概念,异常是出现正常逻辑之外的情况,而错误是指运行时出错了,比如,使用了一个未定义的变量等。异常需要抛出(throw)才能被捕捉到,而错误会导致程序执行终止。
PHP默认情况下,在代码出现了错误,如notice warning等消息时,错误信息会被直接打印到浏览器上,这个时候你通过 try catch是捕获不到错误信息的。php的try catch只能捕获到你自己 throw new Exception(" ")抛出的错误,通过throw之后,程度会直接进入到catch中继续执行。如果你想抛弃php自身的错误处理机制,这个时候可以通过set_error_handler自定义一个函数用来处理,在这个函数中你可以抛出异常,然后再通过catch捕捉到异常。
有关PHP的错误处理可以查看我的上一篇文章:《PHP错误处理机制》
PHP异常介绍
PHP异常一般是指在业务逻辑上出现的不合预期、与正常流程不同的状况,不是语法错误。
PHP异常处理机制借鉴了java c++等,但是PHP的异常处理机制是不健全的。异常处理机制目的是将程序正常执行的代码与出现异常如何处理的代码分离。异常主要有检测(try)、抛出(throw)和捕获(catch)等操作。
PHP异常处理中需要注意的有,当代码中有throw出来的异常,则必须要catch到,也即是一个 try 至少要有一个与之对应的 catch。可以定义多个 catch 可以捕获不同的对象,php会按这些 catch 被定义的顺序执行,直到完成最后一个为止。而在这些 catch 内,又可以抛出新的异常。php的异常也像JAVA的异常的一样,可以在最外层catch捕捉,也可以在throw的地方捕捉。
当一个异常被抛出时,其后的代码将不会继续执行,PHP 会尝试查找匹配的 "catch" 代码块。如果一个异常没有被捕获,而且又没用使用set_exception_handler()作相应的处理的话,那么 PHP 将会产生一个严重的错误,并且输出未能捕获异常(Uncaught Exception ...)的提示信息。
PHP是无法自动捕获异常的(绝大多数),只有主动抛出异常并捕捉。也就是说,对于异常,是可预见的。目前PHP能自动抛出的异常不多,如:PDO类。
相关函数与类
1、set_exception_handler
设置一个用户定义的异常处理函数。
callable set_exception_handler (callable $exception_handler)
该函数设置默认的异常处理程序,用于没有用 try/catch 块来捕获的异常。 在exception_handler调用后异常会中止。
如果把自定义的异常封装到了一个类上,则可以使用数组的方式调用:
set_exception_handler(array('MyExceptionHander' , 'deal')); //MyExceptionHander为异常类,deal为处理方法。
2、register_shutdown_function
通过register_shutdown_function()函数,可以让我们设置一个当执行关闭时可以调用的另一个函数。
当我们的脚本执行完成或意外死掉导致PHP执行即将关闭时,我们的这个函数将会被调用。
该函数的使用场景:1)页面被强制停止;2)程序代码意外终止或超时。
说明:该函数接收一个回调函数作为参数(注意:如果函数里面有写路径一定要写绝对路径,因为执行该回调函数时已经脱离了脚本,是从内存中调用该函数)
3、Exception
Exception是系统自带的异常处理类,是所有异常的基类。主要代码和方法如下:
Exception{
/* 属性 */
protected string $message;
protected int $code;
protected string $file;
protected int $line;
/* 方法 */
public __construct([string $message= "",[int $code= 0[,Exception $previous=NULL]]])
final public string getMessage(void) //获取异常消息内容
final public Exception getPrevious(void) //返回异常链中的前一个异常
final publicint getCode(void) //获取异常代码
final public string getFile(void) //获取发生异常的程序文件名称
final public int getLine(void) //获取发生异常的代码在文件中的行号
final public array getTrace(void) //获取异常追踪信息
final public string getTraceAsString(void) //获取字符串类型的异常追踪信息
public string __toString(void) //将异常对象转换为字符串
final private void __clone(void) //异常克隆
}
常用案例
1、最简单有使用例子
try {
$error = ' Always throw this error ';
throw new Exception($error);
// 从这里开始,try 代码块内的代码将不会被执行
echo ' Never executed ' ;
} catch (Exception $e) {
echo 'Caught exception: ' , $e->getMessage() ;
}
// 继续执行
echo 'Hello Bug';
//输出结果为: Caught exception: Always throw this error Hello Bug
2、自定义异常处理类
// 自定义一个异常处理类
class MyException extends Exception {
public function __construct($message,$code= 0) {
// 继承父类的构造方法,保证所有的变量都被正确赋值
parent::__construct($message,$code);
//下面可以写自己的代码
}
// 重写父类的__toString方法, 自定义字符串输出的样式
public function __toString() {
return __CLASS__.": [{$this->code}]: {$this->message} \n";
}
public function test() {
echo "This is a test. \n";
}
}
//定义好后可以在代码上进行调用,如:
try {
// 抛出自定义异常
throw new MyException('this is my exception', 6);
} catch (Exception $e) { // 捕获异常
echo $e;
}
// 输出结果为: MyException: [6]: this is my exception
3、设置顶层异常处理器
set_exception_handler()函数可设置处理所有未捕获异常的用户定义函数。
function myException($exception){
echo "Exception: " , $exception->getMessage();
}
set_exception_handler('myException');
throw new Exception('Uncaught Exception occurred');
// 上面抛出的异常没有捕获,输出结果为:
// Exception: Uncaught Exception occurred
——《完》——