具有新特性的PHP5之异常处理机制
作者:kitty2702935423 | 来源:互联网 | 2017-06-26 06:42
文章标题:具有新特性的PHP5之异常处理机制。Linux是中国IT实验室的一个技术频道。包含桌面应用,Linux系统管理,内核研究,嵌入式系统和开源等一些基本分类
PHP5之前的错误处理
在PHP5之前的程序错误处理多使用以下三种办法:
1.使用trigger_error()或die()函数来生成一个脚本层次的警告(warning)或致命错误(fatal error);
2.在类方法或函数中返回一个错误标记(如false),也可能设置一个之后可以检查的属性或全局变量(如$error),然后在适合的地方检验其值再决定是否继续执行程序(如if($error==1){});
3.使用PEAR处理错误;
(一)使用die()或trigger_error()
你可以使用die()函数来结束程序运行。以下是一个简单的类,它尝试从一个目录中加载一个类文件。
代码列表 index.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)) {
die("Cannot find $path\n");
}
require_once $path;
if (!class_exists($cmd)) {
die("class $cmd does not exist");
}
$ret = new $cmd();
if (!is_a($ret, 'Command')) {
die("$cmd is not a Command");
}
return $ret;
}
}
?>
这是一个用PHP实现“Command Pattern设计模式”的简单例子(请参看《Java与模式》)。使用这个类的程序员(客户程序员client coder)可以将一个类放到目录中(例中为cmd_php4目录)。一旦文件和其中包含的类同名,并且这个类是Command类的子类,我们的类方法将生成一个可用的Command对象。Command类中定义了一个 execute()方法用来执行找到的命令,即 getCommandObject()方法返回的对象将执行execute().
我们再看看父类Command类,我们将它存在cmd_php4/Command.php文件中。
代码列表cmd_php4/Command.php ?>
// PHP 4
class Command {
function execute() {
die("Command::execute() is an abstract method");
}
}
?>
你可以看到,Command是PHP4中抽象类的实现,我们无法直接将其实例化,而必须先从中派生中子类然后再实例化。当我们使用PHP5后,我们可以使用更好的方式—使用abstract关键字将类和方法声明为“抽象”:
代码列表 ?>
// PHP 5
abstract class Command {
abstract function execute();
}
?>
下面是对上面的抽象类的实现,覆写了execute()方法,在其中加入真正可以执行的内容。这个类命名为realcommand,可以在cmd_php4/realcommand.php文件中找到。
代码列表 cmd_php4/realcommand.php ?>
// PHP 4
require_once 'Command.php';
class realcommand extends Command {
function execute() {
print "realcommand::execute() executing as ordered sah!\n";
}
}
?>
使用这样的结构可以使代码变得很灵活。你可以在任何时候增加新的Command类,而不需要改变外围的框架。但是你不得不注意一些潜在的中止脚本执行的因素。我们需要确保类文件存在,并且在文件中该类存在,并且该类是Command的子类(就像realcommand一样)。
在例子中,如果我们尝试寻找类的操作失败,脚本执行将会中止,这体现了代码的安全性。但这段代码不灵活,没有足够的弹性。极端的反映是类方法只能进行积极正面的操作,它只负责找出和实例化一个Command对象。它无法处理更大范围内脚本执行的错误(当然它也不应该负责处理错误,如果我们给某个类方法加上太多与周边代码的关联,那么这个类的重用将会变得困难,不易扩展)。
尽管使用die()避免了在getCommandObject()方法中嵌入脚本逻辑的危险,它对于对于错误的反应显得过于激烈—-马上中止程序。事实上有时候我们并不希望在找不到想要的类文件时就马上停止执行程序,也许我们有一个默认的命令让程序继续执行。
我们或许可以通过trigger_error()生成一个用户警告来代替,使程序更具有灵活性。
代码列表 Index2.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;
}
}
?>
如果你使用trigger_error()函数来替代die(),你的代码在处理错误上会更具优势,对于客户程序员来说更易于处理错误。trigger_error()接受一个错误信息和一个常量作为参数。常量为:
常量
含义
E_USER_ERROR A fatal error
E_USER_WARNING
A non-fatal error
E_USER_NOTICE
A report that may not represent an error
你可以设计一个错误处理器,然后再定义一个处理器选择函数set_error_handler()来使用这个错误处理器。
代码列表 Index2.php 后半段?>
// PHP 4
function cmdErrorHandler($errnum, $errmsg, $file, $lineno) {
if($errnum == E_USER_ERROR) {
print "error: $errmsg\n";
print "file: $file\n";
print "line: $lineno\n";
exit();
}
}
$handler = set_error_handler('cmdErrorHandler');
$mgr = new CommandManager();
$cmd = $mgr->getCommandObject('realcommand');
$cmd->execute();
?>
set_error_handler()接受一个函数名作为参数。如果触发了一个错误,参数中的这个函数会被调用来处理错误。函数需要传入四个参数:错误标志,错误信息,出错文件,出错处的行数。你也可以将一组数组传递给set_error_handler()。数组中的第一个元素必须是错误处理器将调用的对象,第二个元素是错误处理函数的名称。
可以看出,我们的错误处理器相当简单简陋,还可以改进。然而尽管你可以在错误处理器添加某些功能,如记录出错信息,输出debug数据等,这仍然是一个过于粗糙的错误处理途径。你的选择仅限于已经考虑到的出错情况。例如捕捉一个E_USER_ERROR错误,如果你愿意的话可以不中止脚本的执行(不使用exit()和die()),但如果这样做的话,可能会引起一些很微妙的bug,本来应该中止的程序却继续执行了。
(二) 返回错误标记
脚本层次的错误处理比较粗糙但很有用。尽管如此,我们有时需要更大的灵活性。我们可以使用返回错误标识的办法来告诉客户代码“错误发生了!”。这将程序是否继续,如何继续的责任交给客户代码来决定。
这里我们改进了前面的例子来返回一个脚本执行出错的标志(false是一个常用的不错的选择)。
代码列表 index3.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 4
$mgr = new CommandManager();
$cmd = $mgr->getCommandObject('realcommand');
if (is_bool($cmd)) {
die("error getting command\n");
} else {
$cmd->execute();
}
?>
或者只是记录错误:
代码列表 ?>
// 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 4
推荐阅读
-
本文深入探讨了程序员与软件工程师之间的主要区别,包括它们的职业定位、技能要求以及工作内容等方面的不同,旨在帮助读者更好地理解这两个角色的特点。 ...
[详细]
蜡笔小新 2024-12-03 11:53:09
-
本文汇集了使用C#中不同HTTP客户端向Web API上传文件的实例,旨在为开发者提供实用的技术指南。 ...
[详细]
蜡笔小新 2024-12-04 18:57:41
-
-
本文详细介绍了在PHP中如何创建新文件以及如何使自定义函数在整个项目中全局可用的方法,包括最新的实践技巧。 ...
[详细]
蜡笔小新 2024-12-04 18:48:49
-
本文探讨了在使用phpMyAdmin过程中遇到的mysqli_init()函数错误,并提供了有效的解决方案。 ...
[详细]
蜡笔小新 2024-12-04 17:35:56
-
本文探讨了如何在JavaScript中调用PHP函数及实现两者之间的有效交互,包括通过AJAX请求、动态生成JavaScript代码等方法。 ...
[详细]
蜡笔小新 2024-12-04 16:01:36
-
本文详细介绍了PHP Xdebug的安装步骤及其在PHP开发中的重要作用。Xdebug作为一款强大的调试工具,不仅能够帮助开发者追踪代码执行过程,还能有效提升代码质量和系统性能。 ...
[详细]
蜡笔小新 2024-12-04 15:55:44
-
本文详细介绍了Linux操作系统的文件系统结构,包括其独特的树状目录体系、根目录的作用、目录与磁盘分区的关系等,并对各主要目录的功能进行了深入解析。 ...
[详细]
蜡笔小新 2024-12-04 10:39:45
-
本文详细记录了《PHP与MySQL Web开发》第一章的学习心得,特别关注了PHP的基本构成元素、标记风格、编程注意事项及表单处理技巧等内容。 ...
[详细]
蜡笔小新 2024-12-04 08:25:58
-
本文旨在为信息安全爱好者提供一份详尽的成长指南,涵盖从学习心态调整到具体技能提升的各个方面。 ...
[详细]
蜡笔小新 2024-12-03 19:44:46
-
在现代多线程编程中,Lock接口提供的灵活性和控制力超越了传统的synchronized关键字。Lock接口不仅使锁成为一个独立的对象,还提供了更细粒度的锁定机制,例如读写锁(ReadWriteLock)。本文将探讨如何利用ReentrantReadWriteLock提高并发性能。 ...
[详细]
蜡笔小新 2024-12-03 13:05:03
-
本文详细介绍了在Web开发过程中,遇到CSS文件因MIME类型不匹配而无法正确加载的问题及其解决方案,适合前端开发者阅读。 ...
[详细]
蜡笔小新 2024-12-02 14:32:48
-
本文将探讨iOS开发过程中需要掌握的三种关键编程语言——C、Objective-C和Swift,并深入解析面向过程与面向对象编程的概念,同时对比iOS与Android两大移动平台的特点。 ...
[详细]
蜡笔小新 2024-12-02 11:47:59
-
本文探讨了一个项目中遇到的挑战,即如何通过技术手段解决不同菜单项触发时,跨域IFrame页面的高度自适应问题。通过创建中介页面和利用JavaScript与Cookie机制,实现无缝的用户体验。 ...
[详细]
蜡笔小新 2024-12-04 20:32:23
-
本文介绍了在一卡通项目中设计加密管理方案时,证书服务器的配置步骤及其在用户权限控制中的应用。首先概述了证书服务器的基本设置,包括操作系统的选择和证书服务的安装,随后详细描述了服务器证书及客户端证书的创建过程。 ...
[详细]
蜡笔小新 2024-12-04 18:37:35
-
C#里时关闭子窗口时base.Dispose(disposing)报错:ValueDispose()cannotbecalledwhiledoingCreateHandle(). ...
[详细]
蜡笔小新 2024-12-04 17:40:33
-
kitty2702935423
这个家伙很懒,什么也没留下!