作者:Haohappy 来源:PHPEye.com 2007-01-28
作者: Matt Zandstra
翻译: Haohappy 04-8-20
[email protected]
本文面向的读者
简介
在PHP5之前的错误处理
-使用die()或trigger_error()
-返回错误标记
-使用PEAR处理错误
PHP5的异常机制
-使用throw关键字
-try-catch语句
-处理多个错误
-自定义异常类型
-异常的传递
-更多异常的相关信息
总结
关于作者
本文面向的读者
本文面向希望了解PHP5异常处理机制的程序员。你需要具有一定面向对象编程和PHP基础。
本文集中讨论各种错误处理,在这里你将可以看到PHP4,PHP5中的多种错误处理方式。PHP5引入了“异常机制”――一个在对象体系中进行错误处理的新机制。就像你即将看到的,“异常”提供了不少比传统的错误处理机制先进的特性。
作者:Haohappy 来源:PHPEye.com 2007-01-28 最后更新:2007-02-06 16:43:14
PHP5之前的错误处理
在PHP5之前的程序错误处理多使用以下三种办法:
1.使用trigger_error()或die()函数来生成一个脚本层次的警告(warning)或致命错误(fatal error);
2.在类方法或函数中返回一个错误标记(如false),也可能设置一个之后可以检查的属性或全局变量(如$error),然后在适合的地方检验其值再决定是否继续执行程序(如if($error==1){});
3. 使用PEAR处理错误;
(一)使用die()或trigger_error()
你可以使用die()函数来结束程序运行。以下是一个简单的类,它尝试从一个目录中加载一个类文件。
作者:Haohappy 来源:PHPEye.com 2007-01-28
我们或许可以通过trigger_error()生成一个用户警告来代替,使程序更具有灵活性。
Index2.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
)) {
trigger_error
(
"Cannot find $path"
,
E_USER_ERROR
);
}
require_once
$path
;
if (!
class_exists
(
$cmd
)) {
trigger_error
(
"class $cmd does not exist"
,
E_USER_ERROR
);
}
$ret
= new
$cmd
();
if (!
is_a
(
$ret
,
'Command'
)) {
trigger_error
(
"$cmd is not a Command"
,
E_USER_ERROR
);
}
return
$ret
;
}
}
?>
作者:Haohappy 来源:PHPEye.com 2007-01-28
脚本层次的错误处理比较粗糙但很有用。尽管如此,我们有时需要更大的灵活性。我们可以使用返回错误标识的办法来告诉客户代码“错误发生了!”。这将程序是否继续,如何继续的责任交给客户代码来决定。
这里我们改进了前面的例子来返回一个脚本执行出错的标志(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中提供了更好的解决方案。
作者:Haohappy 来源:PHPEye.com 2007-01-28
(三)使用PEAR处理错误
你也可以使用PEAR来处理错误。当发生错误,将返回一个 Pear_Error
对象。后面的代码通过一个静态方法
PEAR::isError()
来检验这个对象。如果错误确实发生了,那么返回的
Pear_Error
对象将提供你需要的所有相关信息:
|
- the error message 出错信息 |
|
- the |
|
- additional information about the error or its context 附加信息 |
|
- 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"
color: