热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PHP开发学堂:细看Pear的错误处理

文章标题:PHP开发学堂:细看Pear的错误处理。Linux是中国IT实验室的一个技术频道。包含桌面应用,Linux系统管理,内核研究,嵌入式系统和开源等一些基本分类

  许多程序已经使用了PEAR的包。许多PHP程序员或多或少的熟悉了PEAR中的错误处理。但是这个机制并不局限于PEAR的包——所有人都能在他们的类和程序中使用这些方法。
  
  这篇文章被分为两个部分:首先我们将看看类中用于错误处理的函数,然后我们将看看如何基于PEAR错误处理机制来处理错误。
  
  我们的例子类称为cvs2db,它把数据从CSV文件插入到数据库的表中。因为数据可能是手写的,他们的数据应该在插入之前先得到验证——落实postcode。函数import()完成读入,检查和插入的工作;它返回损坏的记录数目。如果返回的值大于0,出错的记录集能够使用exportUnvalid()写入到新的CSV文件中。典型的用法是这样的:
  
    $cd = new csv2db();
  $dsn = 'mysql://root@localhost/csv2db';
  if( 0 <$cd->import("./dat.csv", $dsn, 'address')) {
  $cd->exportUnvalid("./dat2.csv");
  }
  ?>
  
  可能的错误包括:
  
  要导入的CSV文件不存在,
  连接到数据库失败,
  记录集损坏,以及CSV导出文件无法创建。
  
  在提供错误信息的经典解决方案中你可能写这样的代码:
  
    $cd = new csv2db();
  $dsn = 'mysql://root@localhost/csv2db';
  $result = $cd->import("./dat.csv", $dsn, 'address')
  switch($result) {
  case FILE_NOT_OPENED:
  ...
  break;
  case DATABASE_ERROR:
  ...
  break;
  default:
  if(0 <$result) {
  $cd->exportUnvalid("./dat2.csv");
  } else {
  echo 'every thing ok!'
  }
  }
  ?>
  这对于短的脚本来说是可接受的也是常用的办法——但是对于错误处理经常受到关注的大程序来说不是这样。传统的可能性强迫类的作者做最终的决定!在大部分情况下,这个决定根据的是那时对类的调用而不是基于长期的使用和可重用代码的思想。一个灵活的错误处理机制是可重用代码的重要部分,PEAR Error API 就是这样的一种受到良好测试的机制。
  
  用户眼中的类
  除了那两个函数之外,类提供了一套错误处理函数和一个自己的错误对象称为DB2CVS_Error,它有一个特殊的本地化的错误信息的特性功能。
  
  现在我将向你展示如何在错误发生时控制类的行为。
  
  局部和全局错误处理
  你用setErrorHandling()管理错误处理;这个函数需要两个参数:第一个是错误模式,而第二个(可选的)参数是错误模式特定的选项。例如 setErrorHandling(PEAR_ERROR_PRINT, 'This error occurred %s') 还有 setErrorHandling(PEAR_ERROR_TRIGGER, E_USER_WARNING)。
  
  这个函数的调用方式是一般行为中最重要的:静态还是实体。在类cvs2db中,我们能两者都用来设置错误处理,所有这些调用有相同的结构——为类设置错误模式:
  
  // per instance
  $cd = new csv2db();
  $cd->setErrorHandling(PEAR_ERROR_DIE):
  // static
  CVS2DB::setErrorHandling(PEAR_ERROR_DIE);
  PEAR::setErrorHandling(PEAR_ERROR_DIE);
  
  如果两者给出同样的结果,区别在哪?实体调用仅仅为那个类设置而静态调用对于所有使用PEAR_Error或者从那个类派生的所有类起作用。这个也作用于第一个静态命令CVS2DB::setErrorHandling(PEAR_ERROR_DIE)——虽然它看上去仅仅影响了cvs2db类。
  
  总结:作为一个实体函数使用命令意味着仅仅为这个实体(局部)设置错误模式,而作为静态函数来调用就是为整个脚本设置错误模式(全局)。
  
  setErrorHandling() 和 raiseError()
  
  两个函数都能够被静态调用和作为实体的函数调用。记住怎样的一个组合使得他们如何互相影响的很重要。
  
  基本上是:setErrorHandling()的静态调用仅仅影响raiseError()的静态调用——setErrorHandling()作为实体函数仅仅影响raiseError()作为静态函数调用。在类csv2db中,使用csv2db::setErrorHandling()来设置错误模式是不可行的,因为我们使用$this->raiseError(...)。解决这个闻天有一点小技巧——改写raiseError():
  
  function raiseError(...,$mode=null, $optiOns=null,...) {
  if($mode==null && $this->_default_error_mode!=null) {
  $mode = $this->_default_error_mode;
  $optiOns= $this->_default_error_options;
  }
  return PEAR::raiseError(...,$mode, $options,...);
  }
  这样,我们映射实体调用到静态上,如果你用错误模式调用raiseError(),然后这个模式将会覆盖这些设置——这里是指的是全局的设置。
  
  你应当当心错误是如何被类抛出的,如果你不小心,这可能导致不可预期的副作用。
  
  错误的模式
  对错误模式的了解对于使用PEAR的错误处理来说是重要的。PEAR错误处理让用户能够决定怎么去做——注意:下文中术语用户指的的是实际使用PEAR_Error程序的开发者而不是浏览脚本结果或者网页的用户。我将详细展示可能的错误模式。
  
  PEAR_ERROR_DIE——将这个模式开启,程序将终结并且将打印错误信息。可选的,你能定义一个printf()式的字符串,它能够用于产生信息;首先'%s'在字符串中将替代储存在错误对象中的错误信息。
  
  PEAR_ERROR_PRINT——仅仅打印错误信息,包括用于PEAR_ERROR_DIE的同样的可选用的字符串。
  
  PEAR_ERROR_RETURN——当错误发生时的一般行为;你能用类提供isError()函数或者PEAR::isError()检查错误。
  
  $db->setErrorhandling(PEAR_ERROR_RETURN)
  if(!csv2db::isError(0 <$d = $cd->import("./dat.csv", $dsn, 'address'))) {
  if(!csv2db::isError($cd->exportUnvalid("./dat2.csv")) {
  } else {
  // handle error
  }
  } else {
  // handle error
  }
  PEAR_ERROR_TRIGGER——这儿函数向PHP运行时错误行为一样。你必须定义哪种错误应该发生:E_USER_NOTICE,E_USER_WARNING或者E_USER_ERROR。他们直接和PHP本身产生的信息相对应。请注意,在错误信息中错误发生的那行(xxx on line yy)指的是在PEAR.php中调用trigger_error的那行——而不是错误直接发生的那行。
  
  PEAR_ERROR_CALLBACK——这是只在一个地方处理错误并且让你得代码不用考虑错误处理的最佳方式。它需要一个函数或者类函数来捕获错误,你能写一个listing 2中展示的那样的脚本,其中可以看到类相关错误对象的好处:import()函数抛出一个CSV2DB_Error给基于CSV的错误和一个DB_Error对象给相关于数据库访问的错误。
  
  Listing 2
  
  $cd = new csv2db();
  $cd->setErrorHandling(PEAR_ERROR_CALLBACK, 'handleError');
  $dsn = 'mysql://root@localhost/csv2db';
  if( 0 <$d = $cd->import("./dat.csv", $dsn, 'address')) {
  $cd->exportUnvalid("./dat2.csv");
  }
  
  function handleError($error) {
  if(DB::isError($error) {
  // handle database error
  }
  if(csv2db::isError($error) {
  switch($error->getCode()) {
  case FILE_NOT_OPENED :
  ...
  break;
  case CORRUPTED_RECORD :
  ...
  break;
  }
  }
  }
  
  单个的错误处理
  我们有两种可能的错误:我们能够忽略的错误(损坏的记录),以及使得程序无法运行的错误(找不到文件或者打不开数据库)。如果你在shell脚本中使用类,你可以让脚本终止于第二类错误。
  
  自然的,你可以写 $cd->setErrorHandling(PEAR_ERROR_DIE)——但是这可能在如果损坏的记录错误发生时导致问题。在这样的情况下你需要对某个错误停用或者替换错误处理办法的可能。解决办法时expectError(),如果你传递一个错误代码给这个函数,指定错误的错误模式将被单独于缺省错误模式地设置为PEAR_ERROR_RETURN。
  
  expectError()函数把传递来的错误代码储存在栈中,使用popExpected()移出最后传递的错误代码。自从PHP 4.3之后你还能使用delExpect()了;这个函数从栈中删除了指定错误代码的匹配,你不需要关心位置了。
  
  在实际使用中,是这样的:
  
  $cd->setErrorHandling(PEAR_ERROR_DIE);
  ...
  $cd->expectError(CORRUPTED_RECORD);
  $cd->import(...);
  $cd->popExpect();
  
  pushErrorHandling() 和 popErrorHandling() 用起来差不多;他们能够暂时的控制错误处理。例如:如果在 exportUnvalid() 中的文件不能打开,你想要忽略错误:
  
  PEAR::pushErrorHandling(PEAR_ERROR_RETURN);
  $cd->exportUnvalid("./dat2.csv");
  PEAR::popErrorHandling();
  
  注意调用方法的区别!expectError()/popExpect()必须作为实体函数来调用——pushErrorHandling和popErrorHandling可以静态调用。如果作为实体函数,那么他们仅仅影响那个实体。
  
  用户有很多可能性,这是否又意味着程序员要做很多的工作呢?是,是因为你要比return false做更多的事情;否,是因为PEAR Error API给你完成了很多工作。
  
  一些关于错误处理的思考
  作为好的程序员,你不应该从你的类的用户眼中遮掩起确切的错误原因。这阻止了简单的return false的用法;还要注意也可能被PHP自动型别转换为0——这对于import()函数来说意
推荐阅读
  • 解决phpMyAdmin运行错误:mysqli_init(): 属性访问尚未允许
    本文探讨了在使用phpMyAdmin过程中遇到的mysqli_init()函数错误,并提供了有效的解决方案。 ... [详细]
  • 本文探讨了在执行SQL查询时遇到的因字符集不同而导致查询结果差异的问题,特别是涉及中文字符时。文章分析了在不同字符集设置下,SQL查询结果的变化,并提供了详细的解决方案。 ... [详细]
  • 深入解析PHP Xdebug的安装与应用
    本文详细介绍了PHP Xdebug的安装步骤及其在PHP开发中的重要作用。Xdebug作为一款强大的调试工具,不仅能够帮助开发者追踪代码执行过程,还能有效提升代码质量和系统性能。 ... [详细]
  • MySQL中如何为字段添加注释
    本文详细介绍了在MySQL数据库中为字段添加注释的两种方法,并提供了具体的SQL语句示例,帮助开发者更好地管理和理解数据库结构。 ... [详细]
  • 本文详细介绍了如何通过Percona插件监控MySQL 5.7数据库,包括环境准备、插件安装、配置调整及数据测试等步骤,旨在为用户提供一个高效且稳定的监控解决方案。 ... [详细]
  • Django框架的使用教程mysql数据库[三]
    Django的数据库1.在Django_test下的view.py里面model定义模型fromdjango.dbimportmodels#Createyourmodelshere ... [详细]
  • SQL注入实验:SqliLabs第38至45关解析
    本文深入探讨了SqliLabs项目中的第38至45关,重点讲解了堆叠注入(Stacked Queries)的应用技巧及防御策略。通过实际案例分析,帮助读者理解如何利用和防范此类SQL注入攻击。 ... [详细]
  • 本文探讨了梯形图为何成为嵌入式软件机器编程中的理想选择,分析其特点及优势。 ... [详细]
  • KKCMS代码审计初探
    本文主要介绍了KKCMS的安装过程及其基本功能,重点分析了该系统中存在的验证码重用、SQL注入及XSS等安全问题。适合初学者作为入门指南。 ... [详细]
  • 本文详细记录了《PHP与MySQL Web开发》第一章的学习心得,特别关注了PHP的基本构成元素、标记风格、编程注意事项及表单处理技巧等内容。 ... [详细]
  • 本文详细探讨了在不同服务器上运行的PHP程序如何成功连接MySQL数据库的方法,包括常见的连接失败原因及解决方案。 ... [详细]
  • 深入理解FastDFS
    FastDFS是一款高效、简洁的分布式文件系统,广泛应用于互联网应用中,用于处理大量用户上传的文件,如图片、视频等。本文探讨了FastDFS的设计理念及其如何通过独特的架构设计提高性能和可靠性。 ... [详细]
  • 解析程序员与软件工程师的角色差异
    本文深入探讨了程序员与软件工程师之间的主要区别,包括它们的职业定位、技能要求以及工作内容等方面的不同,旨在帮助读者更好地理解这两个角色的特点。 ... [详细]
  • 开发笔记:新手DVWACSRF
    开发笔记:新手DVWACSRF ... [详细]
  • MySQL 索引优化策略与实践
    本文深入探讨了MySQL数据库中的索引优化技术,包括单表索引、多表连接查询索引以及索引失效的常见情况,旨在帮助开发者提高查询效率和数据库性能。 ... [详细]
author-avatar
qinsg688_377
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有