当前位置:Linux教程 - Linux综合 - 具有新特性的PHP5 之异常处理机制

具有新特性的PHP5 之异常处理机制

  PHP5之前的错误处理  在PHP5之前的程序错误处理多使用以下三种办法:  1.使用trigger_error()或die()函数来生成一个脚本层次的警告(warning)或致命错误(fatal error);    2.在类方法或函数中返回一个错误标记(如false),也可能设置一个之后可以检查的属性或全局变量(如$error),然后在适合的地方检验其值再决定是否继续执行程序(如if($error==1){});    3.使用PEAR处理错误;    (一)使用die()或trigger_error()  你可以使用die()函数来结束程序运行。以下是一个简单的类,它尝试从一个目录中加载一个类文件。  <? 代码列表 index.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)) {  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  // PHP 4  class Command {  function execute() {  die("Command::execute() is an abstract method");  }  }  ?>    你可以看到,Command是PHP4中抽象类的实现,我们无法直接将其实例化,而必须先从中派生中子类然后再实例化。当我们使用PHP5后,我们可以使用更好的方式—使用abstract关键字将类和方法声明为“抽象”:    <? 代码列表 ?>    <?php  // PHP 5  abstract class Command {  abstract function execute();  }  ?>      下面是对上面的抽象类的实现,覆写了execute()方法,在其中加入真正可以执行的内容。这个类命名为realcommand,可以在cmd_php4/realcommand.php文件中找到。    <? 代码列表 cmd_php4/realcommand.php ?>    <?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  // 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  // 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  // 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();  }  ?>    或者只是记录错误:    <? 代码列表 ?>    <?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
[1] [2] 下一页 

(出处:http://www.sheup.com)


上一页 [1] [2]