<?php
/**
* Interç»ä»¶FOR PHP4 - é误å¤ç
* ç±äºPHP4å¨é误å¤çä¸çç¹æ®åå ï¼æ¬ç»ä»¶For PHP4æå¦ä¸ç¹ç¹ï¼
* - å
¨é¨æ¢ä¸ºInter_Error_PHP4彿°ç»å
* - ä¸è½å¤çç±»Exceptionï¼å 为PHP4æ²¡è¿æ¦å¿µï¼
*
* PHP5å以ä¸çç请使ç¨Inter_Errorç±»ã
*
* æ¬ç»ä»¶ä¾èµæ§ï¼å¯ç¬ç«ä½¿ç¨ã
* æ¬æä»¶çé误å¤çæè·¯åèè¿ä»¥ä¸ç¨åºï¼å¨æ¤ä¸å¹¶è´è°¢ï¼
* - 论åç¨åºMybb{@link http://www.mybbchina.net/}
* - PHPæ¡æ¶Slightphp{@link http://phpchina.com/bbs/thread-150396-1-1.html}
* - PHPæ¡æ¶DooPHP{@link http://doophp.com/blog/article/diagnostic-debug-view-in-doophp}
*
* @author Horse Luke<hide@address.com>
* @copyright Horse Luke, 2010
* @license the Apache License, Version 2.0 (the "License"). {@link http://www.apache.org/licenses/LICENSE-2.0}
* @version $Id: Inter_Error_PHP4.php 165 2011-02-26 09:19:28Z hide@address.com $
* @package Inter_Component_PHP4
*/
/**
* 设置æè
è·åInter_Error_PHP4彿°ç»åçè®¾ç½®å½æ°ã
* éæåé$confå
·ä½ç设置å¼å¦ä¸ï¼
* debugModeï¼
* æ¯å¦å¼å¯debug模å¼ï¼è¥ä¸ºtrueï¼å°å¨å¨æµè§å¨æ¾ç¤ºè¯¦ç»ä¿¡æ¯ãå¦åå°ä¸æ¾ç¤ºã
* åæ°éæ©ï¼é»è®¤ä¸ºfalseï¼å¯éåæ°trueæè
falseã
* åæ°ç±»åï¼bool
*
* logTypeï¼
* 对é误è¿è¡å
æ¬é误追踪å¨å
ç详ç»è®°å½ï¼detailï¼ãè¿æ¯åªéè¦ç®åè®°å½ï¼simpleï¼ãå使ç¨PHP彿°error_logè¿è¡è®°å½ãï¼
* falseå°ä¸è¿è¡ä»»ä½è®°å½ã
* åæ°éæ©ï¼é»è®¤ä¸ºfalseãå¯éæ©'detail'æè
'simple'æè
å¸å°å¼falseã
* ä¸å»ºè®®å¨ç产ç¯å¢è¿è¡è¯¦ç»è®°å½ï¼detailï¼ï¼å¦åå¨é«è®¿é®éçæ
åµä¸ï¼æ¥å¿çæ¡ç®å°é常混乱ï¼
* åæ°ç±»åï¼bool|string
*
* logDirï¼
* è®°å½æ¥å¿çæä»¶å¤¹ï¼ç®å½è·¯å¾ï¼ï¼ç»å°¾ä¸è¦å«æææ ã
* åæ°éæ©ï¼ é»è®¤ä¸ºç©ºãæ¬åæ°åªæå½logTypeä¸ä¸ºfalseæ¶æææï¼
* å¹¶ä¸å½ä¸ºè¥ä¸ºç©ºãæè
䏿¯ç®å½ãæè
ç®å½ä¸åå¨ï¼åæç
§php.iniç设置è¿è¡é误记å½å¤çã
* åæ°ç±»åï¼string
*
* suffixï¼
* è®°å½æ¥å¿çæä»¶åç¼ã
* åæ°ç±»åï¼string
*
* variablesï¼
* æå®è¦æ£æµåè¾åºçåéåã
* åæ°ç±»åï¼array
*
* ignoreERRORï¼
* ä¸è¦è®°å½çé误类åã
* æ¯å¦ï¼ä¸æ³è®°å½E_NOTICEæè
E_USER_NOTICEé误ï¼åå°æ¤è®¾ç½®ä¸ºarray(E_NOTICE, E_USER_NOTICE)
* å¯ä¼ å
¥ç常éï¼è¯·èªè¡æ¥æ¾ï¼PHPæå -> å½±åPHPè¡ä¸ºçæ©å± -> Error Handling -> é¢å®ä¹å¸¸éã{@link http://docs.php.net/manual/zh/errorfunc.constants.php}
* åæ°ç±»åï¼array
*
*
* @param array|string $name 设置åç§°ãå¦æä¼ å
¥æ°ç»ï¼å表示æ¹é设置ï¼å°è¯¥æ°ç»åå¹¶å°åæè®¾ç½®éé¢å»ï¼
* @param mixed $value 设置å¼ãè¥ä¸ºç©ºï¼å表示è¿åæå®ç$nameç设置å¼ã
* @return mixed
*/
function Inter_Error_PHP4_config( $name, $value = null ){
static $conf = array(
'debugMode' => false,
'logType' => false,
'logDir' => '',
'suffix' => '-Inter-ErrorLog.log',
'variables' => array("_GET", "_POST", "_SESSION", "_COOKIE"),
'ignoreERROR' => array(),
);
if( is_array($name) ){
$conf = array_merge($conf, $name);
return true;
}elseif( is_string($name) ){
if( null !== $value ){
$conf[$name] = $value;
return true;
}else{
return isset( $conf[$name] ) ? $conf[$name] : null;
}
}else{
return null;
}
}
/**
* åå§åInter_Error_PHP4彿°ç»å
* @return bool
*/
function Inter_Error_PHP4_init(){
static $_registered = false;
if (false == $_registered) {
register_shutdown_function ( 'Inter_Error_PHP4_write_errorlog' );
register_shutdown_function ( 'Inter_Error_PHP4_error_display' );
$_registered = true;
}
return true;
}
/**
* è·årequest_uri
* @return string
*/
function Inter_Error_PHP4__get_request_uri(){
static $uri = null;
if(null !== $uri){
return $uri;
}
if(isset($_SERVER['REQUEST_URI'])){
$uri = $_SERVER['REQUEST_URI'];
}elseif(isset($_SERVER['PHP_SELF'])){
if(isset($_SERVER['argv'][0])){
$uri = $_SERVER['PHP_SELF']. '?'. $_SERVER['argv'][0];
}elseif(isset($_SERVER['QUERY_STRING'])){
$uri = $_SERVER['PHP_SELF']. '?'. $_SERVER['QUERY_STRING'];
}else{
$uri = $_SERVER['PHP_SELF'];
}
}else{
$uri = '_UNKNOWN_URI_';
}
return $uri;
}
/**
* å¤çPHPåç°çé误
*
* @param integer $errno é误代å·
* @param string $errstr é误信æ¯
* @param string $errfile é误æå¨æä»¶
* @param string $errline é误æå¨è¡
*/
function Inter_Error_PHP4_error_handler($errno, $errstr, $errfile, $errline){
//echo $errno. $errstr. $errfile. $errline.'<br />';
//对errorç±»åè¿è¡ç´è§åå¤ç~
static $errorText = array("1"=>"E_ERROR",
"2"=>"E_WARNING",
"4"=>"E_PARSE",
"8"=>"E_NOTICE",
"16"=>"E_CORE_ERROR",
"32"=>"E_CORE_WARNING",
"64"=>"E_COMPILE_ERROR",
"128"=>"E_COMPILE_WARNING",
"256"=>"E_USER_ERROR",
"512"=>"E_USER_WARNING",
"1024"=>"E_USER_NOTICE",
"2047"=>"E_ALL",
"2048"=>"E_STRICT"
);
Inter_Error_PHP4_init();
$ignoreError = Inter_Error_PHP4_config('ignoreERROR');
if (empty ( $ignoreError ) || ! in_array ( $errno, $ignoreError )) {
$errorInfo = array ();
$errorInfo ['time'] = time ();
$errorInfo ['type'] = 'ERROR';
if (! empty ( $errorText [$errno] )) {
$errorInfo ['name'] = $errorText [$errno];
} else {
$errorInfo ['name'] = '__UNKNOWN';
}
$errorInfo ['code'] = $errno;
$errorInfo ['message'] = $errstr;
$errorInfo ['file'] = $errfile;
$errorInfo ['line'] = $errline;
$trace = debug_backtrace ();
unset ( $trace [0] ); //è°ç¨è¯¥ç±»èªèº«çerror_handleræ¹æ³æäº§ççtraceï¼æ
å é¤
$errorInfo ['trace'] = Inter_Error_PHP4__format_trace ( $trace );
Inter_Error_PHP4_log($errorInfo);
}
//éè¦æå¨å¯¹FATAL ERRORé误è¿è¡åæ¢
if( in_array($errno, array(1, 4, 16, 64, 256 )) ){
die();
}
}
/**
* è®°å½é误信æ¯ï¼æè
è¿åææé误信æ¯çå卿°ç»
* @param array $value éè¦è®°å½çé误ï¼è¥ä¸ä¼ å
¥å表示è¿åå
¨é¨å·²ç»è®°å½çé误
* @return mixed
*/
function Inter_Error_PHP4_log( $value = null ){
static $_allError = array();
if( !is_array($value) ){
return $_allError;
}else{
$_allError[] = $value;
return true;
}
}
/**
* (ç§æ)对éè¯¯åæº¯è¿½è¸ªä¿¡æ¯è¿è¡æ ¼å¼åè¾åºå¤çã
*
* @param array $trace éè¯¯åæº¯è¿½è¸ªä¿¡æ¯æ°ç»
* @return array $trace éè¯¯åæº¯è¿½è¸ªä¿¡æ¯æ°ç»
*/
function Inter_Error_PHP4__format_trace($trace){
$return = array ();
//éæ¡è¿½è¸ªè®°å½å¤ç
foreach ( $trace as $stack => $detail ) {
if (! empty ( $detail ['args'] )) {
$args_string = Inter_Error_PHP4__args_to_string ( $detail ['args'] );
} else {
$args_string = '';
}
//è§è追踪记å½ï¼ææ
¨PHP太è¿èªç±ï¼è¿traceè®°å½ä¹æ¯ä¸å°½ç¸å-_-||ï¼
$return [$stack] ['class'] = isset ( $trace [$stack] ['class'] ) ? $trace [$stack] ['class'] : '';
$return [$stack] ['type'] = isset ( $trace [$stack] ['type'] ) ? $trace [$stack] ['type'] : '';
//åªæåå¨functionçæ¶åï¼æå¯è½åå¨argsï¼æ
以æ¤åå¹¶ä¹
$return [$stack] ['function'] = isset ( $trace [$stack] ['function'] ) ? $trace [$stack] ['function'] . '(' . $args_string . ')' : '';
$return [$stack] ['file'] = isset ( $trace [$stack] ['file'] ) ? $trace [$stack] ['file'] : '';
$return [$stack] ['line'] = isset ( $trace [$stack] ['line'] ) ? $trace [$stack] ['line'] : '';
}
return $return;
}
/**
* (ç§æ)å°åæ°è½¬å为å¯è¯»çå符串
* åæ±åå°$e->getTraceAsString()çææ
*
* @param array $args
* @return string
*/
function Inter_Error_PHP4__args_to_string($args){
$string = '';
$argsAll = array ();
foreach ( $args as $key => $value ) {
if (true == is_object ( $value )) {
$argsAll [$key] = 'Object(' . get_class ( $value ) . ')';
} elseif (true == is_numeric ( $value )) {
$argsAll [$key] = $value;
} elseif (true == is_string ( $value )) {
$temp = $value;
if (! extension_loaded ( 'mbstring' )) {
if (strlen ( $temp ) > 300) {
$temp = substr ( $temp, 0, 300 ) . '...';
}
} else {
if (mb_strlen ( $temp ) > 300) {
$temp = mb_substr ( $temp, 0, 300 ) . '...';
}
}
$argsAll [$key] = "'{$temp}'";
$temp = null;
} elseif (true == is_bool ( $value )) {
if (true == $value) {
$argsAll [$key] = 'true';
} else {
$argsAll [$key] = 'false';
}
} else {
$argsAll [$key] = gettype ( $value );
}
}
$string = implode ( ',', $argsAll );
return $string;
}
function Inter_Error_PHP4_write_errorlog(){
$conf_logType = Inter_Error_PHP4_config('logType');
if ( false == $conf_logType ){
return null;
}
$allError = Inter_Error_PHP4_log();
if( empty($allError) ){
return null;
}
$logText = '';
foreach ( $allError as $key => $errorInfo ) {
$logText .= date ( "Y-m-d H:i:s", $errorInfo ['time'] ) . "\t" . Inter_Error_PHP4__get_request_uri() . "\t" . $errorInfo ['type'] . "\t" . $errorInfo ['name'] . "\t" . 'Code ' . $errorInfo ['code'] . "\t" . $errorInfo ['message'] . "\t" . $errorInfo ['file'] . "\t" . 'Line ' . $errorInfo ['line'] . "\n";
if ('detail' == $conf_logType && ! empty ( $errorInfo ['trace'] )) {
$prefix = "TRACE\t#";
foreach ( $errorInfo ['trace'] as $stack => $trace ) {
$logText .= $prefix . $stack . "\t" . $trace ['file'] . "\t" . $trace ['line'] . "\t" . $trace ['class'] . $trace ['type'] . $trace ['function'] . "\n";
}
}
}
$conf_logDir = Inter_Error_PHP4_config('logDir');
if (empty ( $conf_logDir ) || false == is_dir ( $conf_logDir )) {
error_log ( $logText );
} else {
$logFilename = date ( "Y-m-d", time () ) . Inter_Error_PHP4_config('suffix');
error_log ( $logText, 3, $conf_logDir . DIRECTORY_SEPARATOR . $logFilename );
}
}
function Inter_Error_PHP4_error_display(){
$conf_debugMode = Inter_Error_PHP4_config('debugMode');
if ( false == $conf_debugMode ){
return null;
}
$allError = Inter_Error_PHP4_log();
if( !empty($allError) ){
$htmlText = '';
foreach ($allError as $key => $errorInfo){
//é误div头
$htmlText .= '<div class="intererrorblock">
<div class="intererrortitle">['.$errorInfo['name'].'][Code '.$errorInfo['code'].'] '.$errorInfo['message'].'</div>
<div class="intererrorsubtitle">Line '.$errorInfo['line'].' On <a href="'.$errorInfo['file'].'">'.$errorInfo['file'].'</a></div>
<div class="intererrorcontent">
';
//traceæ¾ç¤ºåº
if(empty($errorInfo['trace'])){
$htmlText .= 'No Traceable Information.';
}else{
$htmlText .= '<table width="100%" border="1" cellpadding="1" cellspacing="1" rules="rows">
<tr>
<th scope="col">#</th>
<th scope="col">File</th>
<th scope="col">Line</th>
<th scope="col">Class::Method(Args)</th>
</tr>';
foreach ($errorInfo['trace'] as $stack => $trace){
$htmlText .= '<tr>
<td>'.$stack.'</td>
<td><a href="'.$trace['file'].'">'.$trace['file'].'</a></td>
<td>'.$trace['line'].'</td>
<td>'.$trace['class']. $trace['type']. htmlspecialchars($trace['function']) .'</td>
</tr>';
}
$htmlText .= '</table>';
}
//é误divå°¾
$htmlText .= ' </div>
</div>
';
}
//è¾åº
echo <<<END
<style type="text/css">
<!--
.intererrorblock {
font-size: 12pt;
background-color: #FFC;
text-align: left;
vertical-align: middle;
display: inline-block;
border-collapse: collapse;
word-break: break-all;
padding: 3px;
width: 100%;
}
.intererrorblock a:link {
color: #00F;
text-decoration: none;
}
.intererrorblock a:visited {
text-decoration: none;
color: #00F;
}
.intererrorblock a:hover {
text-decoration: underline;
color: #00F;
}
.intererrorblock a:active {
text-decoration: none;
color: #00F;
}
.intererrortitle {
color: #FFF;
background-color: #963;
padding: 3px;
font-weight: bold;
}
.intererrorsubtitle {
padding: 3px;
font-weight: bold;
color: #F00;
}
.intererrorcontent {
font-size: 11pt;
color: #000;
background-color: #FFF;
padding: 3px;
}
.intererrorcontent table{
font-size:14px;
word-break: break-all;
background-color:#D4D0C8;
border-color:#000000;
}
.intererrorblock table a:link {
color: #00F;
text-decoration: none;
}
.intererrorblock table a:visited {
text-decoration: none;
color: #00F;
}
.intererrorblock table a:hover {
text-decoration: underline;
color: #00F;
}
.intererrorblock table a:active {
text-decoration: none;
color: #00F;
}
-->
</style>
{$htmlText}
END;
Inter_Error_PHP4_show_variables();
}
}
/**
* æå®åé忣æµåæ¾ç¤º
*/
function Inter_Error_PHP4_show_variables(){
$variables_link = '';
$variables_content = '';
$conf_variables = Inter_Error_PHP4_config('variables');
foreach( $conf_variables as $key ){
$variables_link .= '<a href="#variables'.$key.'">$'.$key.'</a> ';
$variables_content .= '<div class="variablessubtitle"><a name="variables'.$key.'" id="variables'.$key.'"></a><strong>$'.$key.'</strong></div>
<div class="variablescontent">';
if(!isset($GLOBALS[$key])){
$variables_content .= '$'. $key .' IS NOT SET.';
}else{
$variables_content .= nl2br(htmlspecialchars(var_export($GLOBALS[$key], true)));
}
$variables_content .= '</div>';
}
//è¾åº
echo <<<END
<style type="text/css">
<!--
.variablesblock {
font-size: 12pt;
background-color: #CCC;
text-align: left;
vertical-align: middle;
display: inline-block;
border-collapse: collapse;
word-break: break-all;
padding: 3px;
width: 100%;
color: #000;
}
.variablesblock a:link {
color: #000;
text-decoration: none;
}
.variablesblock a:visited {
text-decoration: none;
color: #000;
}
.variablesblock a:hover {
text-decoration: underline;
color: #000;
}
.variablesblock a:active {
text-decoration: none;
color: #000;
}
.variablessubtitle {
padding: 3px;
font-weight: bold;
border: 1px solid #FFF;
}
.variablescontent {
font-size: 11pt;
color: #000;
background-color: #FFF;
padding: 3px;
}
-->
</style>
<div class="variablesblock">
<div class="variablessubtitle">Variables: {$variables_link}</div>
{$variables_content}
</div>
END;
}