具有新特性的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
推荐阅读
-
本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ...
[详细]
蜡笔小新 2024-12-26 13:21:38
-
本文探讨了并发编程中的关键设计原则,特别是Java内存模型(JMM)的happens-before规则及其对多线程编程的影响。文章详细介绍了DCL双重检查锁定模式的问题及解决方案,并总结了不同处理器和内存模型之间的关系,旨在为程序员提供更深入的理解和最佳实践。 ...
[详细]
蜡笔小新 2024-12-26 01:14:06
-
-
本文介绍了OAuth认证协议的核心概念及其工作原理。OAuth是一种开放标准,旨在为第三方应用提供安全的用户资源访问授权,同时确保用户的账户信息(如用户名和密码)不会暴露给第三方。 ...
[详细]
蜡笔小新 2024-12-28 12:07:46
-
本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ...
[详细]
蜡笔小新 2024-12-28 11:52:00
-
本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ...
[详细]
蜡笔小新 2024-12-28 10:36:30
-
在计算机技术的学习道路上,51CTO学院以其专业性和专注度给我留下了深刻印象。从2012年接触计算机到2014年开始系统学习网络技术和安全领域,51CTO学院始终是我信赖的学习平台。 ...
[详细]
蜡笔小新 2024-12-28 08:20:07
-
1:有如下一段程序:packagea.b.c;publicclassTest{privatestaticinti0;publicintgetNext(){return ...
[详细]
蜡笔小新 2024-12-27 19:32:17
-
本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ...
[详细]
蜡笔小新 2024-12-27 19:31:05
-
本文详细介绍了SQL中的视图、存储过程和事务的概念及应用。视图为用户提供了一种灵活的数据查询方式,存储过程则封装了复杂的SQL逻辑,而事务确保了数据库操作的完整性和一致性。 ...
[详细]
蜡笔小新 2024-12-27 17:40:42
-
本文详细介绍了macOS系统的核心组件,包括如何管理其安全特性——系统完整性保护(SIP),并探讨了不同版本的更新亮点。对于使用macOS系统的用户来说,了解这些信息有助于更好地管理和优化系统性能。 ...
[详细]
蜡笔小新 2024-12-26 18:05:04
-
本文详细介绍了Java泛型的概念及其在JDK 5中的应用,通过具体代码示例解释了泛型的引入、作用和优势。同时,探讨了泛型类、泛型方法和泛型接口的实现,并深入讲解了通配符的使用。 ...
[详细]
蜡笔小新 2024-12-26 11:15:56
-
随着网络安全威胁的不断演变,电子邮件系统成为攻击者频繁利用的目标。本文详细探讨了电子邮件系统中的常见漏洞及其潜在风险,并提供了专业的防护建议。 ...
[详细]
蜡笔小新 2024-12-25 17:59:04
-
TechStride 成立于2014年初,致力于互联网前沿技术、产品创意及创业内容的聚合、搜索、学习与展示。我们旨在为互联网从业者提供更高效的新技术搜索、学习、分享和产品推广平台。 ...
[详细]
蜡笔小新 2024-12-24 20:04:54
-
本文详细记录了网易严选Java开发岗位的面试经验,特别针对MySQL索引相关的技术问题进行了深入探讨。通过本文,读者可以了解面试官常问的索引问题及其背后的原理。 ...
[详细]
蜡笔小新 2024-12-24 19:50:16
-
本文探讨了Hive中内部表和外部表的区别及其在HDFS上的路径映射,详细解释了两者的创建、加载及删除操作,并提供了查看表详细信息的方法。通过对比这两种表类型,帮助读者理解如何更好地管理和保护数据。 ...
[详细]
蜡笔小新 2024-12-27 20:21:48
-
kitty2702935423
这个家伙很懒,什么也没留下!