(三)使用PEAR处理错误
你也可以使用PEAR来处理错误。当发生错误,将返回一个 Pear_Error 对象。后面的代码通过一个静态方法 PEAR::isError() 来检验这个对象。如果错误确实发生了,那么返回的 Pear_Error 对象将提供你需要的所有相关信息:
PEAR::getMessage()
|
- the error message 出错信息 |
PEAR::getType()
|
- the Pear_Error subtype 错误类型 |
PEAR::getUserInfo()
|
- additional information about the error or its context 附加信息 |
PEAR::getCode()
|
- the error code (if any) 出错代码 |
这里我们修改了getCommandObject() 方法,使之返回一个 Pear_Error 对象。
index_pear.php
// PHP 4
require_once( "PEAR.php" );
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 PEAR :: RaiseError ( "Cannot find $path" );
????????}
????????require_once $path ;
????????if (! class_exists ( $cmd )) {
????????????return
???????????? PEAR :: RaiseError ( "class $cmd does not exist" );
????????}
???????? $ret = new $cmd ();
????????if (! is_a ( $ret , 'Command' )) {
????????????return
???????????? PEAR :: RaiseError ( "$cmd is not a Command" );
????????}
????????return $ret ;
????}
}
?>
Pear_Error 既是出错标志又包含有错误的相关具体信息,这对于客户代码来说是很好用的。
// PHP 4
$mgr = new CommandManager ();
$cmd = $mgr -> getCommandObject ( 'realcommand' );
if ( PEAR :: isError ( $cmd )) {
????print $cmd -> getMessage (). "\n" ;
????exit;
}
$cmd -> execute ();
?>
尽管返回一个对象值可以让你灵活对程序中的问题作出反映,它也有“污染接口”的副作用。因为现在 getCommandObject() 方法 的 出口有两个,而且都是对象,有时可能产生混淆。
PHP不允许你指明一个类方法或函数应当返回的值的类型,尽管这样比较方便。 getCommandObject() 方法返回的即是 Command 对象或者一个 Pear_Error 对象。如果你想得到一定的类型的返回值,你必须每次都检验值的类型。一段谨慎的代码会充满复杂的检验条件语句,如果每种类型都检验的话。
以下是一段不考虑错误检验的 PEAR::DB 客户代码
// PHP 4
require_once( "DB.php" );
$db = "errors.db" ;
unlink ( $db );
$dsn = "sqlite://./$db" ;
$db = DB :: connect ( $dsn );
$create_result = $db -> query ( "CREATE TABLE records(name varchar(255))" );
$insert_result = $db -> query ( "INSERT INTO records values('OK Computer')" );
$query_result = $db -> query ( "SELECT * FROM records" );
$row = $query_result -> fetchRow ( DB_FETCHMODE_ASSOC );
print $row [ 'name' ]. "\n" ;
$drop_result = $db -> query ( "drop TABLE records" );
$db -> disconnect ();
?>
程序的可读性很好,操作一目了然--我们选择一个数据库,新建一个数据表然后插入一行纪录,再取回数据,然后丢弃掉数据表。
再看看以下使用错误判断之后:
// PHP 4
require_once( "DB.php" );
$db = "errors.db" ;
unlink ( $db );
$dsn = "sqlite://./$db" ;
$db = DB :: connect ( $dsn );
if ( DB :: isError ( $db )) {
????die ( $db -> getMessage ());
}
$create_result = $db -> query ( "CREATE TABLE records (name varchar(255))" );
if ( DB :: isError ( $create_result )) {
????die ( $create_result -> getMessage ());
}
$insert_result = $db -> query ( "INSERT INTO records values('OK Computer')" );
if ( DB :: isError ( $insert_result )) {
????die ( $insert_result -> getMessage ());
}
$query_result = $db -> query ( "SELECT * FROM records" );
if ( DB :: isError ( $query_result )) {
????die ( $query_result -> getMessage ());
}
$row = $query_result -> fetchRow ( DB_FETCHMODE_ASSOC );
print $row [ 'name' ]. "\n" ;
$drop_result = $db -> query ( "drop TABLE records" );
if ( DB :: isError ( $drop_result )) {
????die ( $drop_result -> getMessage ());
}
$db -> disconnect ();
?>
很明显加上错误检验后,代码显得冗长复杂。其实以上代码比起实际项目中的代码还要简单一些,但已经足以说明错误检验的复杂程度。 
|