问题:
1、错误处理的方法有哪些?
2、使用函数返回值还是抛出异常?
3、PHP 原框架下的异常处理机制是怎样的?
4、PHP Yii 框架下的错误处理方案是怎样的?有什么参考意义?
如上所述四种处理方法,成员变量的方式多数使用在处理结果不用立即返回的情况,譬如对多个数据字段进行校验返回校验结果,使用场景比较明确。触发事件就主要依赖于框架来实现,复杂的处理逻辑可以考虑,使用场景也相对明确。而函数返回值和抛出异常则用得比较纠结,在编写代码的时候就时常需要考虑什么时候使用异常处理,什么时候考虑返回值,而且在嵌套较深的时候还会让人好好纠结一番。
综上所述,使用哪种方式来反馈错误,的确是要看场景。个人觉得,操作频率高的代码模块尽量少使用异常处理,但是要确保返回信息的简洁。而一些失败因素无法穷举的场景,如果不会出现性能问题,则考虑使用异常。
使用异常的基本思路是抛出异常、捕捉异常、处理异常。如下代码所示,可以在任何你希望的地方,通过 throw 语句来抛出异常对象。
- throw new 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;
- }
- }
- 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 '你好呀'; //程序没有崩溃继续向下执行
yii 框架的异常定义集中在 vendor\yiisoft\yii2\base 目录下,但是限于个人能力,还有部分代码没看懂…
UML 的类图结构如下:
1、其中从 PHP 原生异常对象中扩展 ErrorException,用于代表所有虚拟机级别的异常,可能需要重启服务才可以重新提供服务。
2、扩展 UnexpectedValueException,用于不可知的异常,也就是模糊无法定位具体原因的异常。
3、扩展 BadMethodCallException,用于调用不正确的类、方法、错误参数等。
4、扩展 Exception,代表框架内部一些专有的报错信息,例如加载配置文件失败、架构初始化异常等等。
从 Yii 框架的异常类的定义来看,PHP 语言的内部异常类的确不足够用于所有的场景,而不同名字的异常又充当了 errorCode 的角色,无形中也是带框架内部加了不少的 if 分支。
来源: http://lib.csdn.net/article/php/42837