您的位置:首页 > 编程语言 > PHP开发

PHP基础补全系列:异常处理

2016-12-06 18:20 357 查看
异常处理在PHP里也是个很有争议的问题,记得之前做项目的时候,关于异常处理和当时的同事讨论了很久。

不过今天不讨论这些东西,只是单纯做个记录。

这篇博客分三个部分:

异常处理的基本使用
扩展中抛出的异常,以PDO举例
将错误信息委托给异常处理

一些需要注意的tips:

可以使用set_exception_handler自定义异常处理函数(在博客中没写demo)
在PHP7之前的版本中,原生PHP不会抛出异常,异常都需要用户自定义抛出
finally关键字在5.5版本由鸟哥加入PHP,之前的版本没有finally
据说在PHP7版本中,大部分的错误处理都会通过异常的方式抛出(时间原因,没有尝试,等以后写错误处理的时候,会将这个补上)

异常处理的基本使用

需要注意以下几点:

PHP7之前的版本,原生PHP代码不会抛出异常,需要用户自己抛出
finally代码块一定会执行
如果catch代码块中处理完异常并返回结果之后,finally代码块会继续执行,并且finally的返回值会覆盖catch代码块的返回值

具体见代码:

<?php

function division ($a, $b) {
if(!$b) {
throw new Exception("Division by zero");
}
return $a / $b;
}

try {
$result = division(5, 0);
} catch (Exception $e) {
echo $e->getMessage();
}

//结果:异常被捕获,输出"Division by zero"

class User_Exception extends Exception {
}

function user_division ($a, $b) {
if(!$b) {
throw new User_Exception("User division by zero");
}
return $a / $b;
}

try {
$result = division(5, 0);
} catch (User_Exception $e) {
echo $e->getMessage();
} catch (Exception $e) {
echo $e->getMessage();
}
//异常被捕获,输出"Division by zero"

try {
$result = user_division(5, 0);
} catch (User_Exception $e) {
echo $e->getMessage();
} catch (Exception $e) {
echo $e->getMessage();
}
//异常被捕获,输出"User division by zero"

try {
$result = division(5, 0);
} catch (User_Exception $e) {
echo $e->getMessage();
} catch (Exception $e) {
echo $e->getMessage();
} finally {
echo "finally is excuted";
}
//异常被捕获,finally代码被执行,输出"Division by zerofinally is excuted";
//需要特别之处,finally这个特性是由鸟哥在PHP5.5的版本实现的,见鸟哥的博客http://www.laruence.com/2012/08/16/2709.html
//另一个需要注意的地方是,如果在catch代码块中返回了结果,finally还是会继续执行,并且finally的返回值会覆盖catch中的返回值

function testFinally () {
try {
throw new Exception("test Finally");
} catch (Exception $e) {
echo "catch exception\n";
return 0;
} finally {
echo "finally executed\n";
return 1;
}
}

echo testFinally();
/**
* catch和finally代码块均执行,输出结果为
* catch exception
* finally executed
* 1
* catch代码块的返回值被finally代码块的返回值覆盖
*/


PDO扩展的demo

PDO的连接错误都会默认抛出异常,但是不做设置的话,查询错误会返回false

具体见代码:

<?php

try {
$db = new PDO("mysql:host=127.0.0.1;dbname=test", "root", "");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$result = $db->query("SELECT `name` FROM UnknownTable;");
} catch (PDOException $e) {
echo "Catch exception:" . $e->getMessage();
}
//异常被捕获,输出"Catch exception:SQLSTATE[HY000] [2002] Connection refused"
//这个地方特别有意思,如果不设置错误处理方式,连接错误会默认抛出一个PDO异常,但是查询错误默认会返回false;

set_error_handler(function ($error, $errorstr) {
echo $errorstr;
});

try {
$db = new PDO("mysql:host=127.0.0.1;dbname=blog", "root", "");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
$db->query("SELECT * FROM UnknownTable");
} catch (PDOException $e) {
echo "Catch exception:" . $e->getMessage();
}
//将错误处理设置为PDO::ERRMODE_WARNING,不会抛出异常,而是提示一个warning信息.
//这里特别有意思的地方是,如果我不做处理,命令行里会提示两个报警信息.如果我加入set_error_handler,将错误信息打印出来,则只有一个warning信息.
//感觉有时间可以写两篇关于PDO扩展和PHP错误处理的博客


将错误信息委托给异常处理

其实就是设置自定义错误处理函数,将错误信息构造出一个新的异常抛出
需要特别注意异常的构造,这里写的比较简单

具体见代码:

<?php

class Error_Exception extends Exception {
function __construct ($message = "", $code = 0, $severity = 1, $filename = __FILE__, $lineno = __LINE__, $previous = NULL) {
parent::__construct($message, $code);
}
}

set_error_handler(function ($errno, $errstr, $errfile, $errline) {
throw new Error_Exception($errstr, 0, $errno, $errfile, $errline);
});
try {
$result = 5 / 0;
} catch (Error_Exception $e) {
echo $e->getMessage();
}
//异常被捕获,输出"Division by zero"
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: