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

错误处理之函数返回值OR异常处理

2016-05-06 11:04 447 查看
问题:

1、错误处理的方法有哪些?

2、使用函数返回值还是抛出异常?

3、PHP 原框架下的异常处理机制是怎样的?

4、PHP Yii框架下的错误处理方案是怎样的?有什么参考意义?

错误处理的方法有哪些?

函数返回值:既return true|false,数组,对象 等

使用成员变量保存错误信息:在对象内部预设一个 errors变量(可能更多的时候是一个数组),把内部处理的报错信息暂存起来,最后使用getErrors函数获取错误信息。

抛出异常

触发事件:需要框架支持。

暂时只想到这么多了,盼指正!

使用函数返回值还是抛出异常

如上所述四种处理方法,成员变量的方式多数使用在处理结果不用立即返回的情况,譬如对多个数据字段进行校验返回校验结果,使用场景比较明确。触发事件就主要依赖于框架来实现,复杂的处理逻辑可以考虑,使用场景也相对明确。而函数返回值和抛出异常则用得比较纠结,在编写代码的时候就时常需要考虑什么时候使用异常处理,什么时候考虑返回值,而且在嵌套较深的时候还会让人好好纠结一番。

函数返回值的特点

1)函数返回值比较直接,可以使用true|flase直接表达处理结果,使用状态代码来表示更多的执行结果(推荐使用http的状态码,易读易懂),使用数据或者对象来携带更多的数据,性能较高。

2)返回值的修改、添加、减少会对依赖方带来改动,如果调用的地方很多,修改起来也很麻烦。添加返回值后还需要调用方添加相应的处理代码,往往表现为一个if语句。

3)嵌套很深时,层层都需要对返回值进行处理,层层都需要显式判断,会带来不少冗余代码,而且经常出现处理漏状态的情况。

异常处理

1)异常处理是面向对象语言的处理方案,把错误信息抽象为固定的对象,携带着对象固有的报错信息、格式等等,具有较高的可读性,可能从异常名字就可以判断报错类型。

2)使用异常来处理报错信息,可以让程序变得更简洁,代码只需要关注主流程,省了很多状态判断。同时开发语言的异常处理机制封装了很详细的报错信息,便于定位问题。

3)对调用方依赖较少,新增的异常也不需要一定要求调用方去处理,调用方只需要关注该处理的异常即可。即使深层嵌套也可以把底层异常有效暴露给顶层。

4)异常处理是一种对象处理,而且try和catch也会对数据的出入栈带来消耗,所以性能稍低,这点不难理解。

5)开发人员需要对各种各样的异常创建类定义,开发成本较高。

综上所述,使用哪种方式来反馈错误,的确是要看场景。个人觉得,操作频率高的代码模块尽量少使用异常处理,但是要确保返回信息的简洁。而一些失败因素无法穷举的场景,如果不会出现性能问题,则考虑使用异常。

PHP 原框架下的异常处理机制是怎样的

使用异常的基本思路是抛出异常、捕捉异常、处理异常。如下代码所示,可以在任何你希望的地方,通过throw语句来抛出异常对象。

抛出异常

throw new Exception("错误描述,描述清楚错误原因和可能的解决方案...");


捕捉异常

如果异常没有被捕获,而且又没用使用 set_exception_handler() 作相应的处理的话,那么将发生一个严重的错误(致命错误),并且输出 “Uncaught Exception” (未捕获异常)的错误消息。

try
{
//If the exception is thrown, this text will not be shown
}
catch(Exception $e)
{
echo 'Message: ' .$e->getMessage();
}


以上是PHP语言中最基本的异常处理代码,Exception对象是PHP内置的异常类,只是简单得接收异常message,然后展示message。

自定义异常类

一个更成熟的做法是根据自己系统的业务特点来定义异常类,然后处理特定业务场景的异常,实现一种另类的条件选择结构。。如下例子,在找不到对应的商品的时候可以抛出找不到商品异常对象。

class goodsNotFoundException extends Exception
{
public function errorMessage()
{
//error message
$errorMsg = '找不到 '.$this->getMessage().' 这个商品.';
return $errorMsg;
}
}


设置顶层异常处理器 (Top Level Exception Handler)

可以设置顶层异常处理类来处理所有异常。

set_exception_handler('allException');


扩展阅读

Exception 的源码阅读:

class Exception {
protected $message = 'Unknown exception';       //异常信息
private $string;
protected $code = 0;                //用户自定义异常代码
protected $file;              //发生异常的文件名
protected $line;             //发生异常的代码行号
private $trace;
private $previous;
final private function __clone () {} //还不知道什么场景下需要用到
function __construct($message = null, $code = 0){}    //构造方法
/* 不可重载的方法 */
final function getMessage(){}          //返回异常信息
final function getCode(){}             //返回异常代码
final function getFile(){}              //返回发生异常的文件名
final function getLine(){}              //返回发生异常的代码行号
final function getTrace(){}             //backtrace() 数组
final function getTraceAsString(){}     //已格成化成字符串的 getTrace() 信息
/* 可重载的方法 */
function __toString(){}               //可输出的字符串
}


上面这段代码只为说明内置异常处理类Exception的结构,并不是一段有实际意义的可用代码,在IDE里查看PHP的源码基本都是这样的结构代码,内部实现是C代码,在src包里面可以找到。如果使用自定义的类作为异常处理类,则必须是扩展内置异常处理类Exception,非Exception类的子类是不能作为异常处理类使用的。如果在扩展内置处理类Exception时重新定义构造函数的话,建议同时调用parent::construct()来检查所有的变量是否已被赋值。当对象要输出字符串的时候,可以重载__toString()并自定义输出的样式。可以在自定义的子类中,直接使用内置异常处理Exception类中的所有成员属性,但不能重新改写从该父类中继承过来的成员方法,因为该类的大多数公有方法都是final的。

网上摘录了一段样例代码,供参考!

/* 自定义的一个异常处理类,但必须是扩展内异常处理类的子类 */
class MyException extends Exception{
//重定义构造器使第一个参数 message 变为必须被指定的属性
public function __construct($message, $code=0){
//可以在这里定义一些自己的代码
//建议同时调用 parent::construct()来检查所有的变量是否已被赋值
parent::__construct($message, $code);
}
public function __toString() {      //重写父类方法,自定义字符串输出的样式
return __CLASS__.":[".$this->code."]:".$this->message."<br>";
}
public function customFunction() {       //为这个异常自定义一个处理方法

echo "按自定义的方法处理出现的这个类型的异常<br>";

}
}

try {
//使用自定义的异常类捕获一个异常,并处理异常
$error = '允许抛出这个错误';
throw new MyException($error);         //创建一个自定义的异常类对象,通过throw语句抛出
echo 'Never executed';          //从这里开始,try代码块内的代码将不会再被执行
} catch (MyException $e) {          //捕获自定义的异常对象
echo '捕获异常: '.$e;    //输出捕获的异常消息
$e->customFunction();         //通过自定义的异常对象中的方法处理异常
}
echo '你好呀';        //程序没有崩溃继续向下执行


PHP Yii框架下的错误处理方案是怎样的?有什么参考意义?

yii框架的异常定义集中在vendor\yiisoft\yii2\base目录下,但是限于个人能力,还有部分代码没看懂…

UML的类图结构如下:

1、其中从PHP原生异常对象中扩展 ErrorException,用于代表所有虚拟机级别的异常,可能需要重启服务才可以重新提供服务。

2、扩展UnexpectedValueException,用于不可知的异常,也就是模糊无法定位具体原因的异常。

3、扩展BadMethodCallException,用于调用不正确的类、方法、错误参数等。

4、扩展Exception,代表框架内部一些专有的报错信息,例如加载配置文件失败、架构初始化异常等等。





从Yii框架的异常类的定义来看,PHP语言的内部异常类的确不足够用于所有的场景,而不同名字的异常又充当了 errorCode的角色,无形中也是带框架内部加了不少的if分支。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  php 异常处理 yii