set_error_handler
error_types 可选择参数
就像error_reporting 的 ini 设置能够控制错误的显示一样, 此参数能够用于屏蔽 error_handler 的触发。
如果没有该掩码, 无论 error_reporting 是如何设置的, error_handler 都会在每个错误发生时被调用。
error_handler 并不是可以拦截所有的错误,比如下面的几种错误是系统级别的,用户自定义方法拦截不到。
以下级别的错误不能由用户定义的函数来处理: E_ERROR、 E_PARSE、 E_CORE_ERROR、 E_CORE_WARNING、 E_COMPILE_ERROR、 E_COMPILE_WARNING,和在 调用 set_error_handler() 函数所在文件中产生的大多数 E_STRICT。
set_error_handler( function ($severity, $message, $file, $line) use($path){
// $log=[];
// $log[]=$severity;
// $log[]=$message;
// $log[]=$file;
// $log[]=$line;
// // file_put_contents($path.'/log.txt', implode("\n",$log),FILE_APPEND);
// file_put_contents($path.'/log.txt', implode("\n",$log)."\n",FILE_APPEND);
throw new ErrorException($message, 0, $severity, $file, $line);
});如果之前有定义过错误处理程序,则返回该程序名称的 string;
如果是内置的错误处理程序,则返回 NULL。
如果你指定了一个无效的回调函数,同样会返回 NULL。
如果之前的错误处理程序是一个类的方法,此函数会返回一个带类和方法名的索引数组(indexed array)。
同时注意,在需要时你有责任使用 die()。 如果错误处理程序返回了,脚本将会继续执行发生错误的后一行。
private $levels = array( E_DEPRECATED => 'Deprecated', E_USER_DEPRECATED => 'User Deprecated', E_NOTICE => 'Notice', E_USER_NOTICE => 'User Notice', E_STRICT => 'Runtime Notice', E_WARNING => 'Warning', E_USER_WARNING => 'User Warning', E_COMPILE_WARNING => 'Compile Warning', E_CORE_WARNING => 'Core Warning', E_USER_ERROR => 'User Error', E_RECOVERABLE_ERROR => 'Catchable Fatal Error', E_COMPILE_ERROR => 'Compile Error', E_PARSE => 'Parse Error', E_ERROR => 'Error', E_CORE_ERROR => 'Core Error', ); private $loggers = array( E_DEPRECATED => array(null, LogLevel::INFO), E_USER_DEPRECATED => array(null, LogLevel::INFO), E_NOTICE => array(null, LogLevel::WARNING), E_USER_NOTICE => array(null, LogLevel::WARNING), E_STRICT => array(null, LogLevel::WARNING), E_WARNING => array(null, LogLevel::WARNING), E_USER_WARNING => array(null, LogLevel::WARNING), E_COMPILE_WARNING => array(null, LogLevel::WARNING), E_CORE_WARNING => array(null, LogLevel::WARNING), E_USER_ERROR => array(null, LogLevel::CRITICAL), E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL), E_COMPILE_ERROR => array(null, LogLevel::CRITICAL), E_PARSE => array(null, LogLevel::CRITICAL), E_ERROR => array(null, LogLevel::CRITICAL), E_CORE_ERROR => array(null, LogLevel::CRITICAL), );
有第二个参数
可选择参数
就像error_reporting 的 ini 设置能够控制错误的显示一样, 此参数能够用于屏蔽 error_handler 的触发。
如果没有该掩码, 无论 error_reporting 是如何设置的, error_handler 都会在每个错误发生时被调用。
下面实例,我要过滤掉notice的错误。
set_error_handler( function ($severity, $message, $file, $line){
throw new ErrorException($message, 0, $severity, $file, $line);
},E_NOTICE);切记一点:
使用了用户自定义 错误 set_error_handler 函数后, error_get_last() 函数 将获取不到错误信息,
如果还想后续使用error_get_last() 获取错误,需要 在 set_error_handler 最后 强制 使用 return false
用户自定义错误示例:
set_error_handler(function ($severity, $message, $file, $line) use($path){
$errorType = [
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',
2048 => 'E_STRICT',
4096 => 'E_RECOVERABLE_ERROR',
8192 => 'E_DEPRECATED',
16384 => 'E_USER_DEPRECATED',
];
$errorMsg = [
'type' => $severity,
'level' => $errorType[$severity] ?? 'Unknown Error',
'file' => $file,
'line' => $line,
'message' => $message,
];
$errorMsg[]='当前error_reporting的值'.error_reporting();
file_put_contents($path.'/testerror.log',date('Y-m-d H:i:s')."\n".var_export($errorMsg,true)."\n",FILE_APPEND);
return false;
});set_exception_handler
function showExceptionInfoWithHtml(\Throwable $e): void
{
$errorType = get_class($e);
$errorMsg = $e->getMessage();
$code = $e->getCode();
$file = $e->getFile();
$line = $e->getLine();
$traceString = $e->getTraceAsString();
$traceString = explode('#', $traceString);
$traceString = implode('<br />#', $traceString);
$traceString = substr($traceString, 6);
$htmlTemplate = '<div style="border:1px dodgerblue;font-size:18px;line-height:2.0em;padding:10px;">' . PHP_EOL;
$htmlTemplate .= '<div><i>Error Type:</i> <b>%s</b></div>' . PHP_EOL;
$htmlTemplate .= '<div><i>Error Message:</i> <b>%s</b></div>' . PHP_EOL;
$htmlTemplate .= '<div><i>Error Code:</i> <b style="color:red;">%d</b></div>' . PHP_EOL;
$htmlTemplate .= '<div><i>File:</i> <b>%s</b>, on line <b style="color:red;"> %s</b>.</div>' . PHP_EOL;
$htmlTemplate .= '<div><div style="margin-top:20px;"><i><b>Stack Trace:</b></i></div>%s</div></div>' . PHP_EOL;
printf($htmlTemplate, $errorType, $errorMsg, $code, $file, $line, $traceString);
}set_exception_handler 执行顺序
<?php
function log_exception( Exception $e )
{
try{
print_r('后执行...');
throw $e;
}catch(LoadException $e){
print_r('这是load异常...');
}catch(SdkException $e){
print_r('这是sdk异常...');
}finally{
$message = "Type: " . get_class( $e ) . "; Message: {$e->getMessage()}; File: {$e->getFile()}; Line: {$e->getLine()};";
file_put_contents( __DIR__ . "/exceptions.log", $message . PHP_EOL, FILE_APPEND );
}
}
class LoadException extends RuntimeException
{
}
class SdkException extends RuntimeException
{
}
set_exception_handler( "log_exception" );
try{
// throw new SdkException('sss');
throw new mysqli_sql_exception('mysql');
}catch(mysqli_sql_exception $e){
print_r('mysql错误,有可能没有数据没有插入成功...');
}catch(Exception $e){
print_r('先执行...');
throw $e;
}执行结果:
先执行...后执行...这是sdk异常...
另外说明 Exception 是不能捕获到 mysqli_sql_exception 异常的。
register_shutdown_function
register_shutdown_function(
function () use ($path){
$endMicroTime = microtime(true);
$requestInfo = [
'project' => '',
'uri' => $_SERVER['REQUEST_URI'],
'start-time' => date('Y-m-d H:i:s', (int)REQUEST_TIME_START),
'end-time' => date('Y-m-d H:i:s', (int)$endMicroTime),
'run-time' => (($endMicroTime - REQUEST_TIME_START) * 1000) . 'ms'
];
file_put_contents($path.'/log.txt',var_export($requestInfo,true)."\n",FILE_APPEND);
// 最后一次错误处理
if (! empty($errorInfo = error_get_last())) {
$errorType = [
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',
2048 => 'E_STRICT',
4096 => 'E_RECOVERABLE_ERROR',
8192 => 'E_DEPRECATED',
16384 => 'E_USER_DEPRECATED',
];
file_put_contents($path.'/log.txt',var_export($errorInfo,true)."\n",FILE_APPEND);
$errorMsg = [
'type' => $errorInfo['type'],
'level' => $errorType[$errorInfo['type']] ?? 'Unknown Error',
'file' => $errorInfo['file'],
'line' => $errorInfo['line'],
'message' => $errorInfo['message'],
];
file_put_contents($path.'/log.txt',var_export($errorMsg,true)."\n",FILE_APPEND);
}
});整体代码
<?php
define('REQUEST_TIME_START',$_SERVER['REQUEST_TIME_FLOAT']);
error_reporting(-1);
ini_set('display_errors',1);
$path=__DIR__;
set_error_handler( function ($severity, $message, $file, $line) use($path){
// $log=[];
// $log[]=$severity;
// $log[]=$message;
// $log[]=$file;
// $log[]=$line;
// // file_put_contents($path.'/log.txt', implode("\n",$log),FILE_APPEND);
// file_put_contents($path.'/log.txt', implode("\n",$log)."\n",FILE_APPEND);
throw new ErrorException($message, 0, $severity, $file, $line);
});
register_shutdown_function(
function () use ($path){
$endMicroTime = microtime(true);
$requestInfo = [
'project' => '',
'uri' => $_SERVER['REQUEST_URI'],
'start-time' => date('Y-m-d H:i:s', (int)REQUEST_TIME_START),
'end-time' => date('Y-m-d H:i:s', (int)$endMicroTime),
'run-time' => (($endMicroTime - REQUEST_TIME_START) * 1000) . 'ms'
];
file_put_contents($path.'/log.txt',var_export($requestInfo,true)."\n",FILE_APPEND);
// $backtrace=debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
// var_dump($backtrace);
var_dump($bbbb);
// 最后一次错误处理
if (! empty($errorInfo = error_get_last())) {
$errorType = [
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',
2048 => 'E_STRICT',
4096 => 'E_RECOVERABLE_ERROR',
8192 => 'E_DEPRECATED',
16384 => 'E_USER_DEPRECATED',
];
file_put_contents($path.'/log.txt',var_export($errorInfo,true)."\n",FILE_APPEND);
$errorMsg = [
'type' => $errorInfo['type'],
'level' => $errorType[$errorInfo['type']] ?? 'Unknown Error',
'file' => $errorInfo['file'],
'line' => $errorInfo['line'],
'message' => $errorInfo['message'],
];
file_put_contents($path.'/log.txt',var_export($errorMsg,true)."\n",FILE_APPEND);
}
});
try{
echo 111;
function a (){
b();
}
function b($name){
}
function c(){
a();
}
c();
//throw new ErrorException('cuole ');
}catch(Exception $e){
//print_r(debug_backtrace());
// print_r($e);
showExceptionInfoWithHtml($e);
}
function showExceptionInfoWithHtml(\Throwable $e)
{
$errorType = get_class($e);
$errorMsg = $e->getMessage();
$code = $e->getCode();
$file = $e->getFile();
$line = $e->getLine();
$traceString = $e->getTraceAsString();
$traceString = explode('#', $traceString);
$traceString = implode('<br />#', $traceString);
$traceString = substr($traceString, 6);
$htmlTemplate = '<div style="border:1px dodgerblue;font-size:18px;line-height:2.0em;padding:10px;">' . PHP_EOL;
$htmlTemplate .= '<div><i>Error Type:</i> <b>%s</b></div>' . PHP_EOL;
$htmlTemplate .= '<div><i>Error Message:</i> <b>%s</b></div>' . PHP_EOL;
$htmlTemplate .= '<div><i>Error Code:</i> <b style="color:red;">%d</b></div>' . PHP_EOL;
$htmlTemplate .= '<div><i>File:</i> <b>%s</b>, on line <b style="color:red;"> %s</b>.</div>' . PHP_EOL;
$htmlTemplate .= '<div><div style="margin-top:20px;"><i><b>Stack Trace:</b></i></div>%s</div></div>' . PHP_EOL;
printf($htmlTemplate, $errorType, $errorMsg, $code, $file, $line, $traceString);
}