php_错误处理机制
- 格式:pdf
- 大小:175.86 KB
- 文档页数:18
exit(); } ?>
可以看到,通过结合使用 throw 关键字和 try-catch 语句,我们可以避免错误标记“污染”类方法返 回的值。因为“异常”本身就是一种与其它任何对象不同的 PHP 内建的类型,不会产生混淆。 如果抛出了一个异常,try 语句中的脚本将会停止执行,然后马上转向执行 catch 语句中的脚本。 如果异常抛出了却没有被捕捉到,就会产生一个 fatal error。
这里有两个地方的调用可能导致程序出错(__construct()和
getCommandObject())。尽管如此,我们不需要调整我们的客户代码。你可以在 try 语句中增
getErrorStr()、 getError()和 error()等功能相同的函数。
然而,实际开发中要让程序中的所有类都从同一个类中继承而来是很困难的,除非同时使用接口 (interface)否则无法实现一些子类自身特有的功能, 但那已经是 PHP5 的内容。 就像我们将提到的, PHP5 中提供了更好的解决方案。
同时处理多个错误
在目前为止异常处理看起来和我们传统的作法—检验返回的错误标识或对象的值没有什么太大区别。让我 们将 CommandManager 处理地更谨慎, 并在构造函数中检查 command 目录是否存在。 index_php5_2.php
<?php // PHP 5 require_once('cmd_php5/Command.php'); class CommandManager { private $cmdDir = "cmd_php5";
返回 Error flag(错误标记)
脚本层次的错误处理比较粗糙但很有用。尽管如此,我们有时需要更大的灵活性。我们可以使用返回 错误标识的办法来告诉客户代码“错误发生了!”。这将程序是否继续,如何继续的责任交给客户代码来决 定。 这里我们改进了前面的例子来返回一个脚本执行出错的标志(false 是一个常用的不错的选择)。
function __construct() { if (!is_dir($this->cmdDir)) { throw new Exception( "directory error: $this->cmdDir"); } } function getCommandObject($cmd) { $path = "{$this->cmdDir}/{$cmd}.php"; if (!file_exists($path)) { throw new Exception("Cannot finction setError($method, $msg) { $this->error_str =
get_class($this)."::{$method}(): $msg";
} function error() { return $this->error_str; } function getCommandObject($cmd) { $path = "{$this->cmdDir}/{$cmd}.php"; if (!file_exists($path)) { $this->setError(__FUNCTION__, "Cannot find $path\n"); return false; } require_once $path;
if (!class_exists($cmd)) { $this->setError(__FUNCTION__, "class $cmd does not exist"); return false; } $ret = new $cmd(); if (!is_a($ret, 'Command')) { $this->setError(__FUNCTION__, "$cmd is not a
index3.php <?php // PHP 4 require_once('cmd_php4/Command.php'); class CommandManager { var $cmdDir = "cmd_php4";
function getCommandObject($cmd) { $path = "{$this->cmdDir}/{$cmd}.php"; if (!file_exists($path)) { return false; } require_once $path;
建立一个 Exception 对象后你可以将对象返回,但不应该这样使用,更好的方法是用 throw 关键字来代 替。throw 用来抛出异常:
throw new Exception( "my message", 44 );
throw 将脚本的执行中止,并使相关的 Exception 对象对客户代码可用。 以下是改进过的 getCommandObject()
Command"); return false; } return $ret; } } ?>
这个简单的机制可以让 setError()记录下错误信息。其它代码可以通过 error()来获得脚本错 误的相关信息。你应该将这个功能抽取出来并放在一个最基本的类中,其它所用类都从这个类继承而来。 这样可以统一处理错误,否则可能出现混乱。我就曾经见过有些程序在不同的类中使用
require_once $path; if (!class_exists($cmd)) { throw new Exception("class $cmd does not exist"); } $class = new ReflectionClass($cmd); if (!$class->isSubclassOf(new ReflectionClass('Command'))) { throw new Exception("$cmd is not a Command"); } return new $cmd(); } } ?>
PHP5 内建的Exception类
PHP5 的异常机制
根据我们以上讨论的,PHP 内建的异常类需要有以下成员方法:
__construct() getMessage() getCode() getFile() getLine() getTrace() 构造函数,需要一个出错信息和一个可选的整型错误标记作参数 取得出错信息 出错的代码 异常发生的文件 异常发生的行数 跟踪异常每一步传递的路线,存入数组,返回该数组 和 getTrace()功能一样,但可以将数组中的元素转成字符串并按一定格式输 getTraceAsString() 出
方法:
index_php5.php <?php // PHP 5 require_once('cmd_php5/Command.php'); class CommandManager { private $cmdDir = "cmd_php5";
function getCommandObject($cmd) { $path = "{$this->cmdDir}/{$cmd}.php"; if (!file_exists($path)) { throw new Exception("Cannot find $path"); } require_once $path; if (!class_exists($cmd)) { throw new Exception( "class $cmd does not exist"); } $class = new ReflectionClass($cmd); if (!$class->isSubclassOf(new ReflectionClass('Command'))) {
} else { $cmd->execute(); } ?>
使用像“false”这样的错误标志的好处是直观,但是明显给出的信息量不够,我们无法得知到底是在哪一 个环节上错而导致返回 false。你可以再设置一个 error 属性,这样在产生错误后输出出错信息。 index4.php
<?php // PHP 4 require_once('cmd_php4/Command.php'); class CommandManager { var $cmdDir = "cmd_php4"; var $error_str = "";
throw new Exception("$cmd is not a Command"); } return new $cmd(); } } ?>
代码中我们使用了 PHP5 的反射(Reflection)API 来判断所给的类是否是属于 Command
类型。
在错误的路径下执行本脚本将会报出这样的错误: Fatal error: Uncaught exception 'Exception' with message 'Cannot find command/xrealcommand.php' in /home/xyz/BasicException.php:10 Stack trace: #0 /home/xyz/BasicException.php(26): CommandManager->getCommandObject('xrealcommand') #1 {main} thrown in /home/xyz/BasicException.php on line 10