代码改变世界

极致控制下的异常错误处理

2012-11-25 02:27  游乐场123  阅读(297)  评论(0编辑  收藏  举报

"PHP的try/catch只能捕捉一些异常类型的错误,而一些运行时的错误往往无法获取";
  这句话一定要更改. 如果你在try中,
不使用if判断语句来:throw new Exception($error);的话, 你的catch块就是等到2012也不会被触发. 那既然已经if判断了,
我们为何还要用catch来处理异常呢? 自我定义一个统一函数, 如disucz的showmessage()来处理不是更好?


"set_error_handler也捕捉不到函数不存在"
  的确set_error_handler无法实现,
但我们可以更深层次思考一下, 总要解决这个问题.
让register_shutdown_function+error_get_last来完成才是王道,  这样已经进入内存中运行的error_get_last()终于能够将错误捕捉了,
并且页面加载已经完成, 它仅仅做的是错误记录, 即不影响速度也不影响用户操作, 一切都在后台默默进行中.

个人建议, 无论如何,
都不要打印出异常信息, 不要试着随意去exit($error); 就算异常已经抛出, 作为一个技术员, 你自己也未必看得到, 比如QQ的网站集群,
页面数量那是相当可观的, 你即不可能去一一检查, 也不会有用户天天告诉你哪个页错误了, 在腾讯这种公司, 错误许可犯, 但自己都不知道错误在何时何地,
是不许可的. 建立一套完善的日志系统及追踪功能对腾讯来说非常重要. 它能够知道哪个页面访问量少了, 哪个页面错误异常, 哪个页面加载过慢.
这些都可以用app_htmlout()完成. 所以, 我建议大家都要布置一套这功能块, 让分散的信息全面集中.

下面看看示例.

  1. # 首先防止页面崩溃, 先注册个处理函数.
  2. register_shutdown_function('app_htmlout');
  3. #....................这儿随意写你的代码, 怎么混乱都行.
  4. # 不管中止还是结束访问, 此函数都会被调用起来
  5. function app_htmlout() {
  6.     # 防止多次调用
  7.         static $i = 0;
  8.         empty($i) === false && fun_exit('');
  9.         $i ++;
  10.    
  11.     # php错误获取
  12.     $s = 0;
  13.     $error = '';
  14.    
  15.     # 用error_get_last()取得错误信息
  16.     if(is_null($e = error_get_last()) === false){
  17.          if($e['type'] != 8){  // 去掉nitig的提示错误
  18.              $error = 'PHP:';
  19.              foreach($e as $key => $val){
  20.                 $error .=" $key: $val /";  // 将数据整合到一条, 这儿如何组合,完全看你自己.
  21.              }
  22.              $s = 1;
  23.              $e = null;  // 注销数组.
  24.              $error .="\n";
  25.          }
  26.     }
  27.    
  28.     # 同时对mysql错误进行有效的获取
  29.     if($e = mysql_error()){
  30.         $error .= 'MYSQL: ';
  31.         $error .= $e;
  32.         $error .=' '.$_SERVER['SCRIPT_NAME'].var_export($_GET,true);  // 对执行页php及GET参数进行收集, 以完整表达错误出现的条件是什么.
  33.         $s = 1;
  34.         $error .= "\n";
  35.     }
  36.    
  37.     # 只有$s为1时, 才代表有错误. 所以写入日志, 注意路径一定要绝对的.
  38.     if($s === 1){
  39.         file_put_contents(ROOT."Data/error.log",$error,FILE_APPEND);
  40.     }
  41.    
  42.     # 还可以操作一些其它事宜, 比如关闭mysql连接, 比如清空缓存, 也可以生成静态化文件.
  43.         mysql::close();
  44. }