zl程序教程

您现在的位置是:首页 >  其他

当前栏目

一个显示效果非常不错的PHP错误、异常处理类

错误PHP异常 处理 一个 显示 效果 非常
2023-06-13 09:15:20 时间

一、效果图:


二、实现代码

复制代码代码如下:

<?php

//自定义异常函数
set_exception_handler("handle_exception");

//自定义错误函数
set_error_handler("handle_error");

/**
 *异常处理
 *
 *@parammixed$exception异常对象
 *@authorblog.snsgou.com
 */
functionhandle_exception($exception){
 Error::exceptionError($exception);
}

/**
 *错误处理
 *
 *@paramstring$errNo错误代码
 *@paramstring$errStr错误信息
 *@paramstring$errFile出错文件
 *@paramstring$errLine出错行
 *@authorblog.snsgou.com
 */
functionhandle_error($errNo,$errStr,$errFile,$errLine){
 if($errNo){
  Error::systemError($errStr,false,true,false);
 }
}

/**
 *系统错误处理
 *
 *@authorblog.snsgou.com
 */
classError{

 publicstaticfunctionsystemError($message,$show=true,$save=true,$halt=true){

  list($showTrace,$logTrace)=self::debugBacktrace();

  if($save){
   $messageSave="<b>".$message."</b><br/><b>PHP:</b>".$logTrace;
   self::writeErrorLog($messageSave);
  }

  if($show){
   self::showError("system","<li>$message</li>",$showTrace,0);
  }

  if($halt){
   exit();
  }else{
   return$message;
  }
 }

 /**
 *代码执行过程回溯信息
 *
 *@static
 *@accesspublic
 */
 publicstaticfunctiondebugBacktrace(){
  $skipFunc[]="Error->debugBacktrace";

  $show=$log="";
  $debugBacktrace=debug_backtrace();
  ksort($debugBacktrace);
  foreach($debugBacktraceas$k=>$error){
   if(!isset($error["file"])){
    //利用反射API来获取方法/函数所在的文件和行数
    try{
     if(isset($error["class"])){
      $reflection=newReflectionMethod($error["class"],$error["function"]);
     }else{
      $reflection=newReflectionFunction($error["function"]);
     }
     $error["file"]=$reflection->getFileName();
     $error["line"]=$reflection->getStartLine();
    }catch(Exception$e){
     continue;
    }
   }

   $file=str_replace(SITE_PATH,"",$error["file"]);
   $func=isset($error["class"])?$error["class"]:"";
   $func.=isset($error["type"])?$error["type"]:"";
   $func.=isset($error["function"])?$error["function"]:"";
   if(in_array($func,$skipFunc)){
    break;
   }
   $error["line"]=sprintf("%04d",$error["line"]);

   $show.="<li>[Line:".$error["line"]."]".$file."(".$func.")</li>";
   $log.=!empty($log)?"->":"";
   $log.=$file.":".$error["line"];
  }
  returnarray($show,$log);
 }

 /**
 *异常处理
 *
 *@static
 *@accesspublic
 *@parammixed$exception
 */
 publicstaticfunctionexceptionError($exception){
  if($exceptioninstanceofDbException){
   $type="db";
  }else{
   $type="system";
  }
  if($type=="db"){
   $errorMsg="(".$exception->getCode().")";
   $errorMsg.=self::sqlClear($exception->getMessage(),$exception->getDbConfig());
   if($exception->getSql()){
    $errorMsg.="<divclass="sql">";
    $errorMsg.=self::sqlClear($exception->getSql(),$exception->getDbConfig());
    $errorMsg.="</div>";
   }
  }else{
   $errorMsg=$exception->getMessage();
  }
  $trace=$exception->getTrace();
  krsort($trace);
  $trace[]=array("file"=>$exception->getFile(),"line"=>$exception->getLine(),"function"=>"break");
  $phpMsg=array();
  foreach($traceas$error){
   if(!empty($error["function"])){
    $fun="";
    if(!empty($error["class"])){
     $fun.=$error["class"].$error["type"];
    }
    $fun.=$error["function"]."(";
    if(!empty($error["args"])){
     $mark="";
     foreach($error["args"]as$arg){
      $fun.=$mark;
      if(is_array($arg)){
       $fun.="Array";
      }elseif(is_bool($arg)){
       $fun.=$arg?"true":"false";
      }elseif(is_int($arg)){
       $fun.=(defined("SITE_DEBUG")&&SITE_DEBUG)?$arg:"%d";
      }elseif(is_float($arg)){
       $fun.=(defined("SITE_DEBUG")&&SITE_DEBUG)?$arg:"%f";
      }else{
       $fun.=(defined("SITE_DEBUG")&&SITE_DEBUG)?"\"".htmlspecialchars(substr(self::clear($arg),0,10)).(strlen($arg)>10?"...":"")."\"":"%s";
      }
      $mark=",";
     }
    }
    $fun.=")";
    $error["function"]=$fun;
   }
   if(!isset($error["line"])){
    continue;
   }
   $phpMsg[]=array("file"=>str_replace(array(SITE_PATH,"\\"),array("","/"),$error["file"]),"line"=>$error["line"],"function"=>$error["function"]);
  }
  self::showError($type,$errorMsg,$phpMsg);
  exit();
 }

 /**
 *记录错误日志
 *
 *@static
 *@accesspublic
 *@paramstring$message
 */
 publicstaticfunctionwriteErrorLog($message){

  returnfalse;//暂时不写入

  $message=self::clear($message);
  $time=time();
  $file=LOG_PATH."/".date("Y.m.d")."_errorlog.php";
  $hash=md5($message);

  $userId=0;
  $ip=get_client_ip();

  $user="<b>User:</b>userId=".intval($userId).";IP=".$ip.";RIP:".$_SERVER["REMOTE_ADDR"];
  $uri="Request:".htmlspecialchars(self::clear($_SERVER["REQUEST_URI"]));
  $message="<?phpexit;?>\t{$time}\t$message\t$hash\t$user$uri\n";

  //判断该$message是否在时间间隔$maxtime内已记录过,有,则不用再记录了
  if(is_file($file)){
   $fp=@fopen($file,"rb");
   $lastlen=50000;  //读取最后的$lastlen长度字节内容
   $maxtime=60*10;  //时间间隔:10分钟
   $offset=filesize($file)-$lastlen;
   if($offset>0){
    fseek($fp,$offset);
   }
   if($data=fread($fp,$lastlen)){
    $array=explode("\n",$data);
    if(is_array($array))
     foreach($arrayas$key=>$val){
      $row=explode("\t",$val);
      if($row[0]!="<?phpexit;?>"){
       continue;
      }
      if($row[3]==$hash&&($row[1]>$time-$maxtime)){
       return;
      }
     }
   }
  }

  error_log($message,3,$file);
 }

 /**
 *清除文本部分字符
 *
 *@paramstring$message
 */
 publicstaticfunctionclear($message){
  returnstr_replace(array("\t","\r","\n"),"",$message);
 }

 /**
 *sql语句字符清理
 *
 *@static
 *@accesspublic
 *@paramstring$message
 *@paramstring$dbConfig
 */
 publicstaticfunctionsqlClear($message,$dbConfig){
  $message=self::clear($message);
  if(!(defined("SITE_DEBUG")&&SITE_DEBUG)){
   $message=str_replace($dbConfig["database"],"***",$message);
   //$message=str_replace($dbConfig["prefix"],"***",$message);
   $message=str_replace(C("DB_PREFIX"),"***",$message);
  }
  $message=htmlspecialchars($message);
  return$message;
 }

 /**
 *显示错误
 *
 *@static
 *@accesspublic
 *@paramstring$type错误类型db,system
 *@paramstring$errorMsg
 *@paramstring$phpMsg
 */
 publicstaticfunctionshowError($type,$errorMsg,$phpMsg=""){
  global$_G;

  $errorMsg=str_replace(SITE_PATH,"",$errorMsg);
  ob_end_clean();
  $host=$_SERVER["HTTP_HOST"];
  $title=$type=="db"?"Database":"System";
  echo<<<EOT
<!DOCTYPEhtmlPUBLIC"-//W3C//DTDXHTML1.0Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
 <title>$host-$titleError</title>
 <metahttp-equiv="Content-Type"content="text/html;charset={$_G["config"]["output"]["charset"]}"/>
 <metaname="ROBOTS"content="NOINDEX,NOFOLLOW,NOARCHIVE"/>
 <styletype="text/css">
 <!--
 body{background-color:white;color:black;font:9pt/11ptverdana,arial,sans-serif;}
 #container{margin:10px;}
 #message{width:1024px;color:black;}
 .red{color:red;}
 a:link{font:9pt/11ptverdana,arial,sans-serif;color:red;}
 a:visited{font:9pt/11ptverdana,arial,sans-serif;color:#4e4e4e;}
 h1{color:#FF0000;font:18pt"Verdana";margin-bottom:0.5em;}
 .bg1{background-color:#FFFFCC;}
 .bg2{background-color:#EEEEEE;}
 .table{background:#AAAAAA;font:11ptMenlo,Consolas,"LucidaConsole"}
 .info{
  background:nonerepeatscroll00#F3F3F3;
  border:0pxsolid#aaaaaa;
  border-radius:10px10px10px10px;
  color:#000000;
  font-size:11pt;
  line-height:160%;
  margin-bottom:1em;
  padding:1em;
 }

 .help{
  background:#F3F3F3;
  border-radius:10px10px10px10px;
  font:12pxverdana,arial,sans-serif;
  text-align:center;
  line-height:160%;
  padding:1em;
 }

 .sql{
  background:nonerepeatscroll00#FFFFCC;
  border:1pxsolid#aaaaaa;
  color:#000000;
  font:arial,sans-serif;
  font-size:9pt;
  line-height:160%;
  margin-top:1em;
  padding:4px;
 }
 -->
 </style>
</head>
<body>
<divid="container">
<h1>$titleError</h1>
<divclass="info">$errorMsg</div>
EOT;
  if(!empty($phpMsg)){
   echo"<divclass="info">";
   echo"<p><strong>PHPDebug</strong></p>";
   echo"<tablecellpadding="5"cellspacing="1"width="100%"class="table"><tbody>";
   if(is_array($phpMsg)){
    echo"<trclass="bg2"><td>No.</td><td>File</td><td>Line</td><td>Code</td></tr>";
    foreach($phpMsgas$k=>$msg){
     $k++;
     echo"<trclass="bg1">";
     echo"<td>".$k."</td>";
     echo"<td>".$msg["file"]."</td>";
     echo"<td>".$msg["line"]."</td>";
     echo"<td>".$msg["function"]."</td>";
     echo"</tr>";
    }
   }else{
    echo"<tr><td><ul>".$phpMsg."</ul></td></tr>";
   }
   echo"</tbody></table></div>";
  }
  echo<<<EOT
</div>
</body>
</html>
EOT;
  exit();
 }
}

/**
 *DB异常类
 *
 *@authorblog.snsgou.com
 */
classDbExceptionextendsException{

 protected$sql;
 protected$dbConfig; //当前数据库配置信息

 publicfunction__construct($message,$code=0,$sql="",$dbConfig=array()){
  $this->sql=$sql;
  $this->dbConfig=$dbConfig;
  parent::__construct($message,$code);
 }

 publicfunctiongetSql(){
  return$this->sql;
 }

 publicfunctiongetDbConfig(){
  return$this->dbConfig;
 }
}