(二)返回错误标记
脚本层次的错误处理比较粗糙但很有用。尽管如此,我们有时需要更大的灵活性。我们可以使用返回错误标识的办法来告诉客户代码“错误发生了!”。这将程序是否继续,如何继续的责任交给客户代码来决定。
这里我们改进了前面的例子来返回一个脚本执行出错的标志(false是一个常用的不错的选择)。
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 ;
if (! class_exists ( $cmd )) {
return false ;
}
$ret = new $cmd ();
if (! is_a ( $ret , 'Command' )) {
return false ;
}
return $ret ;
}
}
?>
这意味着你可以根据环境来处理多个错误,而不会在第一个错误发生时马上停止程序的执行。
<?php
// PHP 4
$mgr = new CommandManager ();
$cmd = $mgr -> getCommandObject ( 'realcommand' );
if ( is_bool ( $cmd )) {
die( "error getting command\n" );
} else {
$cmd -> execute ();
}
?>
or just a logged error:
<?php
// PHP 4
$mgr = new CommandManager ();
$cmd = $mgr -> getCommandObject ( 'realcommand' );
if( is_bool ( $cmd )) {
error_log ( "error getting command\n" , 0 );
}
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 = "" ;
function 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 Command" );
return false ;
}
return $ret ;
}
}
?>
这个简单的机制可以让setError() 记 录下错误信息。其它代码可以通过error()来获得脚本错误的相关信息。你应该将这个功能抽取出来并放在一个最基本的类中,其它所用类都从这个类继承而来。这样可以统一处理错误,否则可能出现混乱。我就曾经见过有些程序在不同的类中使用getErrorStr() 、 getError() 和error() 等功能相同的函数。
然而,实际开发中要让程序中的所有类都从同一个类中继承而来是很困难的,除非同时使用接口(interface)否则无法实现一些子类自身特有的功能,但那已经是PHP5的内容。就像我们将提到的,PHP5中提供了更好的解决方案。 
|