拦截PHP各种错误和异常,发生致命异常时进行报警,万事防患于未然
拦截PHP各种异常和错误,发生致命错误时进行报警,万事防患于未然
在日常开发中,大多数人的做法是在开发环境时开启调试模式,在产品环境关闭调试模式。在开发的时候可以查看各种错误、异常,但是在线上就把错误显示的关闭。
上面的情形看似很科学,有人解释为这样很安全,别人看不到错误,以免泄露重要信息...
但是你有没有遇到这种情况,线下好好的,一上线却运行不起来也找不到原因...
一个脚本,跑了好长一段时间,一直没有问题,有一天突然中断了,然后了也没有任何记录都不造啥原因...
线上一个付款,别人明明付了款,但是我们却没有记录到,自己亲自去实验,却是好的...
种种以上,都是因为大家关闭了错误信息,并且未将错误、异常记录到日志,导致那些随机发生的错误很难追踪。这样矛盾就来了,即不要显示错误,又要追踪错误,这如何实现了?
以上问题都可以通过PHP的错误、异常机制及其内建函数'set_exception_handler','set_error_handler','register_shutdown_function' 来实现
'set_exception_handler' 函数 用于拦截各种未捕获的异常,然后将这些交给用户自定义的方式进行处理
'set_error_handler' 函数可以拦截各种错误,然后交给用户自定义的方式进行处理
'register_shutdown_function' 函数是在PHP脚本结束时调用的函数,配合'error_get_last'可以获取最后的致命性错误
这个思路大体就是把错误、异常、致命性错误拦截下来,交给我们自定义的方法进行处理,我们辨别这些错误、异常是否致命,如果是则记录的数据库或者文件系统,然后使用脚本不停的扫描这些日志,发现严重错误立即发送邮件或发送短信进行报警
首先我们定义错误拦截类,该类用于将错误、异常拦截下来,用我们自己定义的处理方式进行处理,该类放在文件名为'errorHandler.class.php'中,代码如下
<span style="color: #008000;">/*</span><span style="color: #008000;">* * 文件名称:baseErrorHandler.class.php * 摘 要:错误拦截器父类 </span><span style="color: #008000;">*/</span><span style="color: #0000ff;">require</span> 'errorHandlerException.class.php';<span style="color: #008000;">//</span><span style="color: #008000;">异常类</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> errorHandler{ </span><span style="color: #0000ff;">public</span> <span style="color: #800080;">$argvs</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">(); </span><span style="color: #0000ff;">public</span> <span style="color: #800080;">$memoryReserveSize</span> = 262144;<span style="color: #008000;">//</span><span style="color: #008000;">备用内存大小</span> <span style="color: #0000ff;">private</span> <span style="color: #800080;">$_memoryReserve</span>;<span style="color: #008000;">//</span><span style="color: #008000;">备用内存</span> <span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:注册自定义错误、异常拦截器 * 参 数:void * 返 回:void </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> register() { </span><span style="color: #008080;">ini_set</span>('display_errors', 0<span style="color: #000000;">); </span><span style="color: #008080;">set_exception_handler</span>(<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>, 'handleException'));<span style="color: #008000;">//</span><span style="color: #008000;">截获未捕获的异常</span> <span style="color: #008080;">set_error_handler</span>(<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>, 'handleError'));<span style="color: #008000;">//</span><span style="color: #008000;">截获各种错误 此处切不可掉换位置 //留下备用内存 供后面拦截致命错误使用</span> <span style="color: #800080;">$this</span>->memoryReserveSize > 0 && <span style="color: #800080;">$this</span>->_memoryReserve = <span style="color: #008080;">str_repeat</span>('x', <span style="color: #800080;">$this</span>-><span style="color: #000000;">memoryReserveSize); </span><span style="color: #008080;">register_shutdown_function</span>(<span style="color: #0000ff;">array</span>(<span style="color: #800080;">$this</span>, 'handleFatalError'));<span style="color: #008000;">//</span><span style="color: #008000;">截获致命性错误</span><span style="color: #000000;"> } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:取消自定义错误、异常拦截器 * 参 数:void * 返 回:void </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> unregister() { </span><span style="color: #008080;">restore_error_handler</span><span style="color: #000000;">(); </span><span style="color: #008080;">restore_exception_handler</span><span style="color: #000000;">(); } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:处理截获的未捕获的异常 * 参 数:Exception $exception * 返 回:void </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> handleException(<span style="color: #800080;">$exception</span><span style="color: #000000;">) { </span><span style="color: #800080;">$this</span>-><span style="color: #000000;">unregister(); </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> { </span><span style="color: #800080;">$this</span>->logException(<span style="color: #800080;">$exception</span><span style="color: #000000;">); </span><span style="color: #0000ff;">exit</span>(1<span style="color: #000000;">); } </span><span style="color: #0000ff;">catch</span>(<span style="color: #0000ff;">Exception</span> <span style="color: #800080;">$e</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">exit</span>(1<span style="color: #000000;">); } } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:处理截获的错误 * 参 数:int $code 错误代码 * 参 数:string $message 错误信息 * 参 数:string $file 错误文件 * 参 数:int $line 错误的行数 * 返 回:boolean </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> handleError(<span style="color: #800080;">$code</span>, <span style="color: #800080;">$message</span>, <span style="color: #800080;">$file</span>, <span style="color: #800080;">$line</span><span style="color: #000000;">) { </span><span style="color: #008000;">//</span><span style="color: #008000;">该处思想是将错误变成异常抛出 统一交给异常处理函数进行处理</span> <span style="color: #0000ff;">if</span>((<span style="color: #008080;">error_reporting</span>() & <span style="color: #800080;">$code</span>) && !<span style="color: #008080;">in_array</span>(<span style="color: #800080;">$code</span>, <span style="color: #0000ff;">array</span>(<span style="color: #ff00ff;">E_NOTICE</span>, <span style="color: #ff00ff;">E_WARNING</span>, <span style="color: #ff00ff;">E_USER_NOTICE</span>, <span style="color: #ff00ff;">E_USER_WARNING</span>,<span style="color: #000000;"> E_DEPRECATED))) {</span><span style="color: #008000;">//</span><span style="color: #008000;">此处只记录严重的错误 对于各种WARNING NOTICE不作处理</span> <span style="color: #800080;">$exception</span> = <span style="color: #0000ff;">new</span> errorHandlerException(<span style="color: #800080;">$message</span>, <span style="color: #800080;">$code</span>, <span style="color: #800080;">$code</span>, <span style="color: #800080;">$file</span>, <span style="color: #800080;">$line</span><span style="color: #000000;">); </span><span style="color: #800080;">$trace</span> = <span style="color: #008080;">debug_backtrace</span><span style="color: #000000;">(DEBUG_BACKTRACE_IGNORE_ARGS); </span><span style="color: #008080;">array_shift</span>(<span style="color: #800080;">$trace</span>);<span style="color: #008000;">//</span><span style="color: #008000;">trace的第一个元素为当前对象 移除</span> <span style="color: #0000ff;">foreach</span>(<span style="color: #800080;">$trace</span> <span style="color: #0000ff;">as</span> <span style="color: #800080;">$frame</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$frame</span>['function'] == '__toString'<span style="color: #000000;">) {</span><span style="color: #008000;">//</span><span style="color: #008000;">如果错误出现在 __toString 方法中 不抛出任何异常</span> <span style="color: #800080;">$this</span>->handleException(<span style="color: #800080;">$exception</span><span style="color: #000000;">); </span><span style="color: #0000ff;">exit</span>(1<span style="color: #000000;">); } } </span><span style="color: #0000ff;">throw</span> <span style="color: #800080;">$exception</span><span style="color: #000000;">; } </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #000000;">; } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:截获致命性错误 * 参 数:void * 返 回:void </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> handleFatalError() { </span><span style="color: #0000ff;">unset</span>(<span style="color: #800080;">$this</span>->_memoryReserve);<span style="color: #008000;">//</span><span style="color: #008000;">释放内存供下面处理程序使用</span> <span style="color: #800080;">$error</span> = error_get_last();<span style="color: #008000;">//</span><span style="color: #008000;">最后一条错误信息</span> <span style="color: #0000ff;">if</span>(errorHandlerException::isFatalError(<span style="color: #800080;">$error</span><span style="color: #000000;">)) {</span><span style="color: #008000;">//</span><span style="color: #008000;">如果是致命错误进行处理</span> <span style="color: #800080;">$exception</span> = <span style="color: #0000ff;">new</span> errorHandlerException(<span style="color: #800080;">$error</span>['message'], <span style="color: #800080;">$error</span>['type'], <span style="color: #800080;">$error</span>['type'], <span style="color: #800080;">$error</span>['file'], <span style="color: #800080;">$error</span>['line'<span style="color: #000000;">]); </span><span style="color: #800080;">$this</span>->logException(<span style="color: #800080;">$exception</span><span style="color: #000000;">); </span><span style="color: #0000ff;">exit</span>(1<span style="color: #000000;">); } } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:获取服务器IP * 参 数:void * 返 回:string </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> getServerIp() { </span><span style="color: #800080;">$serverIp</span> = ''<span style="color: #000000;">; </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$_SERVER</span>['SERVER_ADDR'<span style="color: #000000;">])) { </span><span style="color: #800080;">$serverIp</span> = <span style="color: #800080;">$_SERVER</span>['SERVER_ADDR'<span style="color: #000000;">]; } </span><span style="color: #0000ff;">elseif</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$_SERVER</span>['LOCAL_ADDR'<span style="color: #000000;">])) { </span><span style="color: #800080;">$serverIp</span> = <span style="color: #800080;">$_SERVER</span>['LOCAL_ADDR'<span style="color: #000000;">]; } </span><span style="color: #0000ff;">elseif</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$_SERVER</span>['HOSTNAME'<span style="color: #000000;">])) { </span><span style="color: #800080;">$serverIp</span> = <span style="color: #008080;">gethostbyname</span>(<span style="color: #800080;">$_SERVER</span>['HOSTNAME'<span style="color: #000000;">]); } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> { </span><span style="color: #800080;">$serverIp</span> = <span style="color: #008080;">getenv</span>('SERVER_ADDR'<span style="color: #000000;">); } </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$serverIp</span><span style="color: #000000;">; } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:获取当前URI信息 * 参 数:void * 返 回:string $url </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> getCurrentUri() { </span><span style="color: #800080;">$uri</span> = ''<span style="color: #000000;">; </span><span style="color: #0000ff;">if</span>(<span style="color: #800080;">$_SERVER</span> ["REMOTE_ADDR"<span style="color: #000000;">]) {</span><span style="color: #008000;">//</span><span style="color: #008000;">浏览器浏览模式</span> <span style="color: #800080;">$uri</span> = 'http://' . <span style="color: #800080;">$_SERVER</span>['SERVER_NAME'] . <span style="color: #800080;">$_SERVER</span>['REQUEST_URI'<span style="color: #000000;">]; } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {</span><span style="color: #008000;">//</span><span style="color: #008000;">命令行模式</span> <span style="color: #800080;">$params</span> = <span style="color: #800080;">$this</span>-><span style="color: #000000;">argvs; </span><span style="color: #800080;">$uri</span> = <span style="color: #800080;">$params</span>[0<span style="color: #000000;">]; </span><span style="color: #008080;">array_shift</span>(<span style="color: #800080;">$params</span><span style="color: #000000;">); </span><span style="color: #0000ff;">for</span>(<span style="color: #800080;">$i</span> = 0, <span style="color: #800080;">$len</span> = <span style="color: #008080;">count</span>(<span style="color: #800080;">$params</span>); <span style="color: #800080;">$i</span> $len; <span style="color: #800080;">$i</span>++<span style="color: #000000;">) { </span><span style="color: #800080;">$uri</span> .= ' ' . <span style="color: #800080;">$params</span>[<span style="color: #800080;">$i</span><span style="color: #000000;">]; } } </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$uri</span><span style="color: #000000;">; } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:记录异常信息 * 参 数:errorHandlerException $e 错误异常 * 返 回:boolean 是否保存成功 </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> logException(<span style="color: #800080;">$e</span><span style="color: #000000;">) { </span><span style="color: #800080;">$error</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">( </span>'add_time' => <span style="color: #008080;">time</span>(), 'title' => errorHandlerException::getName(<span style="color: #800080;">$e</span>->getCode()),<span style="color: #008000;">//</span><span style="color: #008000;">这里获取用户友好型名称</span> 'message' => <span style="color: #0000ff;">array</span>(), 'server_ip' => <span style="color: #800080;">$this</span>->getServerIp(), 'code' => errorHandlerException::getLocalCode(<span style="color: #800080;">$e</span>->getCode()),<span style="color: #008000;">//</span><span style="color: #008000;">这里为各种错误定义一个编号以便查找</span> 'file' => <span style="color: #800080;">$e</span>->getFile(), 'line' => <span style="color: #800080;">$e</span>->getLine(), 'url' => <span style="color: #800080;">$this</span>->getCurrentUri(),<span style="color: #000000;"> ); </span><span style="color: #0000ff;">do</span><span style="color: #000000;"> { </span><span style="color: #008000;">//</span><span style="color: #008000;">$e->getFile() . ':' . $e->getLine() . ' ' . $e->getMessage() . '(' . $e->getCode() . ')'</span> <span style="color: #800080;">$message</span> = (<span style="color: #0000ff;">string</span>)<span style="color: #800080;">$e</span><span style="color: #000000;">; </span><span style="color: #800080;">$error</span>['message'][] = <span style="color: #800080;">$message</span><span style="color: #000000;">; } </span><span style="color: #0000ff;">while</span>(<span style="color: #800080;">$e</span> = <span style="color: #800080;">$e</span>-><span style="color: #000000;">getPrevious()); </span><span style="color: #800080;">$error</span>['message'] = <span style="color: #008080;">implode</span>("\r\n", <span style="color: #800080;">$error</span>['message'<span style="color: #000000;">]); </span><span style="color: #800080;">$this</span>->logError(<span style="color: #800080;">$error</span><span style="color: #000000;">); } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:记录异常信息 * 参 数:array $error = array( * 'time' => int, * 'title' => 'string', * 'message' => 'string', * 'code' => int, * 'server_ip' => 'string' * 'file' => 'string', * 'line' => int, * 'url' => 'string', * ); * 返 回:boolean 是否保存成功 </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> logError(<span style="color: #800080;">$error</span><span style="color: #000000;">) { </span><span style="color: #008000;">/*</span><span style="color: #008000;">这里去实现如何将错误信息记录到日志</span><span style="color: #008000;">*/</span><span style="color: #000000;"> }}</span>
上述代码中,有个'errorHandlerException'类,该类放在文件'errorHandlerException.class.php'中,该类用于将错误转换为异常,以便记录错误发生的文件、行号、错误代码、错误信息等信息,同时其方法'isFatalError'用于辨别该错误是否是致命性错误。这里我们为了方便管理,将错误进行编号并命名。该类的代码如下
<span style="color: #008000;">/*</span><span style="color: #008000;">* * 文件名称:errorHandlerException.class.php * 摘 要:自定义错误异常类 该类继承至PHP内置的错误异常类 </span><span style="color: #008000;">*/</span><span style="color: #0000ff;">class</span> errorHandlerException <span style="color: #0000ff;">extends</span><span style="color: #000000;"> ErrorException{ </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #800080;">$localCode</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">( </span><span style="color: #ff00ff;">E_COMPILE_ERROR</span> => 4001, <span style="color: #ff00ff;">E_COMPILE_WARNING</span> => 4002, <span style="color: #ff00ff;">E_CORE_ERROR</span> => 4003, <span style="color: #ff00ff;">E_CORE_WARNING</span> => 4004,<span style="color: #000000;"> E_DEPRECATED </span>=> 4005, <span style="color: #ff00ff;">E_ERROR</span> => 4006, <span style="color: #ff00ff;">E_NOTICE</span> => 4007, <span style="color: #ff00ff;">E_PARSE</span> => 4008,<span style="color: #000000;"> E_RECOVERABLE_ERROR </span>=> 4009, <span style="color: #ff00ff;">E_STRICT</span> => 4010,<span style="color: #000000;"> E_USER_DEPRECATED </span>=> 4011, <span style="color: #ff00ff;">E_USER_ERROR</span> => 4012, <span style="color: #ff00ff;">E_USER_NOTICE</span> => 4013, <span style="color: #ff00ff;">E_USER_WARNING</span> => 4014, <span style="color: #ff00ff;">E_WARNING</span> => 4015, 4016 => 4016,<span style="color: #000000;"> ); </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #800080;">$localName</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">( </span><span style="color: #ff00ff;">E_COMPILE_ERROR</span> => 'PHP Compile Error', <span style="color: #ff00ff;">E_COMPILE_WARNING</span> => 'PHP Compile Warning', <span style="color: #ff00ff;">E_CORE_ERROR</span> => 'PHP Core Error', <span style="color: #ff00ff;">E_CORE_WARNING</span> => 'PHP Core Warning',<span style="color: #000000;"> E_DEPRECATED </span>=> 'PHP Deprecated Warning', <span style="color: #ff00ff;">E_ERROR</span> => 'PHP Fatal Error', <span style="color: #ff00ff;">E_NOTICE</span> => 'PHP Notice', <span style="color: #ff00ff;">E_PARSE</span> => 'PHP Parse Error',<span style="color: #000000;"> E_RECOVERABLE_ERROR </span>=> 'PHP Recoverable Error', <span style="color: #ff00ff;">E_STRICT</span> => 'PHP Strict Warning',<span style="color: #000000;"> E_USER_DEPRECATED </span>=> 'PHP User Deprecated Warning', <span style="color: #ff00ff;">E_USER_ERROR</span> => 'PHP User Error', <span style="color: #ff00ff;">E_USER_NOTICE</span> => 'PHP User Notice', <span style="color: #ff00ff;">E_USER_WARNING</span> => 'PHP User Warning', <span style="color: #ff00ff;">E_WARNING</span> => 'PHP Warning', 4016 => 'Customer`s Error',<span style="color: #000000;"> ); </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:构造函数 * 摘 要:相关知识请查看 http://php.net/manual/en/errorexception.construct.php * * 参 数:string $message 异常信息(可选) * int $code 异常代码(可选) * int $severity * string $filename 异常文件(可选) * int $line 异常的行数(可选) * Exception $previous 上一个异常(可选) * * 返 回:void </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> __construct(<span style="color: #800080;">$message</span> = '', <span style="color: #800080;">$code</span> = 0, <span style="color: #800080;">$severity</span> = 1, <span style="color: #800080;">$filename</span> = <span style="color: #ff00ff;">__FILE__</span>, <span style="color: #800080;">$line</span> = <span style="color: #ff00ff;">__LINE__</span>, <span style="color: #0000ff;">Exception</span> <span style="color: #800080;">$previous</span> = <span style="color: #0000ff;">null</span><span style="color: #000000;">) { parent</span>::__construct(<span style="color: #800080;">$message</span>, <span style="color: #800080;">$code</span>, <span style="color: #800080;">$severity</span>, <span style="color: #800080;">$filename</span>, <span style="color: #800080;">$line</span>, <span style="color: #800080;">$previous</span><span style="color: #000000;">); } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:是否是致命性错误 * 参 数:array $error * 返 回:boolean </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">function</span> isFatalError(<span style="color: #800080;">$error</span><span style="color: #000000;">) { </span><span style="color: #800080;">$fatalErrors</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">( </span><span style="color: #ff00ff;">E_ERROR</span>, <span style="color: #ff00ff;">E_PARSE</span>, <span style="color: #ff00ff;">E_CORE_ERROR</span>, <span style="color: #ff00ff;">E_CORE_WARNING</span>, <span style="color: #ff00ff;">E_COMPILE_ERROR</span>, <span style="color: #ff00ff;">E_COMPILE_WARNING</span><span style="color: #000000;"> ); </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$error</span>['type']) && <span style="color: #008080;">in_array</span>(<span style="color: #800080;">$error</span>['type'], <span style="color: #800080;">$fatalErrors</span><span style="color: #000000;">); } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:根据原始的错误代码得到本地的错误代码 * 参 数:int $code * 返 回:int $localCode </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">function</span> getLocalCode(<span style="color: #800080;">$code</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">isset</span>(self::<span style="color: #800080;">$localCode</span>[<span style="color: #800080;">$code</span>]) ? self::<span style="color: #800080;">$localCode</span>[<span style="color: #800080;">$code</span>] : self::<span style="color: #800080;">$localCode</span>[4016<span style="color: #000000;">]; } </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:根据原始的错误代码获取用户友好型名称 * 参 数:int * 返 回:string $name </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">function</span> getName(<span style="color: #800080;">$code</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">isset</span>(self::<span style="color: #800080;">$localName</span>[<span style="color: #800080;">$code</span>]) ? self::<span style="color: #800080;">$localName</span>[<span style="color: #800080;">$code</span>] : self::<span style="color: #800080;">$localName</span>[4016<span style="color: #000000;">]; }</span>
在错误拦截类中,需要用户自己定义实现错误记录的方法('logException'),这个地方需要注意,有些错误可能在一段时间内不断发生,因此只需记录一次即可,你可以使用错误代码、文件、行号、错误详情 生成一个MD5值用于记录该错误是否已经被记录,如果在规定时间内(一个小时)已经被记录过则不需要再进行记录
然后我们定义一个文件,用于实例化以上类,捕获各种错误、异常,该文件命名为'registerErrorHandler.php', 内如如下
<span style="color: #008000;">/*</span><span style="color: #008000;">* 使用方法介绍:* 在入口处引入该文件即可,然后可以在该文件中定义调试模式常量'DEBUG_ERROR'** <?php * * require 'registerErrorHandler.php';* * ?></span><span style="color: #008000;">*/</span><span style="color: #008000;">/*</span><span style="color: #008000;">** 调试错误模式:* 0 => 非调试模式,不显示异常、错误信息但记录异常、错误信息* 1 => 调试模式,显示异常、错误信息但不记录异常、错误信息</span><span style="color: #008000;">*/</span><span style="color: #008080;">define</span>('DEBUG_ERROR', 0<span style="color: #000000;">);</span><span style="color: #0000ff;">require</span> 'errorHandler.class.php'<span style="color: #000000;">;</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> registerErrorHandler{ </span><span style="color: #008000;">/*</span><span style="color: #008000;">* * 方 法:注册异常、错误拦截 * 参 数:void * 返 回:void </span><span style="color: #008000;">*/</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> register() { </span><span style="color: #0000ff;">global</span> <span style="color: #800080;">$argv</span><span style="color: #000000;">; </span><span style="color: #0000ff;">if</span><span style="color: #000000;">(DEBUG_ERROR) {</span><span style="color: #008000;">//</span><span style="color: #008000;">如果开启调试模式</span> <span style="color: #008080;">ini_set</span>('display_errors', 1<span style="color: #000000;">); </span><span style="color: #0000ff;">return</span><span style="color: #000000;">; } </span><span style="color: #008000;">//</span><span style="color: #008000;">如果不开启调试模式</span> <span style="color: #008080;">ini_set</span>('error_reporting', -1<span style="color: #000000;">); </span><span style="color: #008080;">ini_set</span>('display_errors', 0<span style="color: #000000;">); </span><span style="color: #800080;">$handler</span> = <span style="color: #0000ff;">new</span><span style="color: #000000;"> errorHandler(); </span><span style="color: #800080;">$handler</span>->argvs = <span style="color: #800080;">$argv</span>;<span style="color: #008000;">//</span><span style="color: #008000;">此处主要兼容命令行模式下获取参数</span> <span style="color: #800080;">$handler</span>-><span style="color: #000000;">register(); } }registerErrorHandler</span>::register();
剩下的就是需要你在你的入口文件引入该文件,定义调试模式,然后实现你自己记录错误的方法即可
需要注意的是,有些错误在你进行注册之前已经发生并且导致脚本中断是无法记录下来的,因为此时'registerErrorHandler::register()' 尚未执行已经中断了
还有就是'set_error_handler'这个函数不能捕获下面类型的错误 E_ERROR
、 E_PARSE
、 E_CORE_ERROR
、 E_CORE_WARNING
、E_COMPILE_ERROR
、 E_COMPILE_WARNING, 这个可以在官方文档中看到,但是本处无妨,因为以上错误是解析、编译错误,这些都没有通过,你是不可能发布上线的
以上代码经过严格测试,并且已经应用在线上环境,大家可以根据自己需要进行更改使用

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











많은 사용자들이 스마트 시계를 선택할 때 Huawei 브랜드를 선택하게 됩니다. 그 중 Huawei GT3pro와 GT4가 가장 인기 있는 선택입니다. 두 제품의 차이점을 궁금해하는 사용자가 많습니다. Huawei GT3pro와 GT4의 차이점은 무엇입니까? 1. 외관 GT4: 46mm와 41mm, 재질은 유리 거울 + 스테인레스 스틸 본체 + 고해상도 섬유 후면 쉘입니다. GT3pro: 46.6mm 및 42.9mm, 재질은 사파이어 유리 + 티타늄 본체/세라믹 본체 + 세라믹 백 쉘입니다. 2. 건강한 GT4: 최신 Huawei Truseen5.5+ 알고리즘을 사용하면 결과가 더 정확해집니다. GT3pro: ECG 심전도, 혈관 및 안전성 추가

PHP는 오랫동안 사용되어 온 인기 있는 웹 개발 언어입니다. PHP에 통합된 PDO(PHP 데이터 개체) 클래스는 웹 애플리케이션 개발 중에 데이터베이스와 상호 작용하는 일반적인 방법입니다. 그러나 일부 PHP 개발자가 자주 직면하는 문제는 PDO 클래스를 사용하여 데이터베이스와 상호 작용할 때 다음과 같은 오류가 발생한다는 것입니다. PHPFatalerror:CalltoundefinemethodPDO::prep

Vue 애플리케이션에서 axios를 사용하는 것은 매우 일반적입니다. axios는 브라우저와 Node.js에서 사용할 수 있는 Promise 기반 HTTP 클라이언트입니다. 개발 과정에서 "Uncaught(inpromise)Error: Requestfailedwithstatuscode500"이라는 오류 메시지가 나타나는 경우가 있는데, 개발자 입장에서는 이 오류 메시지를 이해하고 해결하기 어려울 수 있습니다. 이 기사에서는 이에 대해 알아볼 것입니다.

C++ 코드의 "error:incompletetypeisnotallowed" 문제를 해결하십시오. C++ 프로그래밍 프로세스 중에 흔히 발생하는 오류 중 하나는 "error:incompletetypeisnotallowed"입니다. 이 오류는 일반적으로 불완전한 유형에서 작업할 때 발생합니다. 이 문서에서는 이 오류의 원인을 설명하고 몇 가지 해결 방법을 제공합니다. 첫째로, 나는

C++ 코드의 "error:expectedinitializerbefore'datatype'" 문제를 해결하세요. C++ 프로그래밍에서 코드를 작성할 때 가끔 컴파일 오류가 발생하는 경우가 있습니다. 일반적인 오류 중 하나는 "error:expectedinitializerbefore'datatype'"입니다. 이 오류는 일반적으로 변수 선언이나 함수 정의에서 발생하며 프로그램이 올바르게 컴파일되지 않거나

PHP경고:foreach()에 대해 잘못된 인수가 제공되었습니다. -해결 방법 PHP를 사용하여 웹 페이지나 응용 프로그램을 개발할 때 다양한 오류와 경고가 자주 발생합니다. 일반적인 경고 중 하나는 foreach 루프를 사용하여 배열을 반복할 때 일반적으로 생성되는 "Invalidargumentsuppliedforforeach()"입니다. 이 질문은 간단해 보이지만 그렇지 않다면

PHPWarning:fopen():SSLOperationfailedinfile.phponlineX 해결 방법 PHP 프로그래밍에서는 fopen 함수를 사용하여 파일이나 URL을 열고 관련 작업을 수행하는 경우가 많습니다. 그러나 fopen 함수를 사용할 때 때때로 Warning:fopen():SSLOperationfailedinfile.p와 유사한 문제가 발생할 수 있습니다.

PHPWarning:fopen():failedtoopenstream:Nosuchfileordirectory 해결 방법 PHP 개발을 사용하는 과정에서 "PHPWarning:fopen():failedtoopenstream:Nosuchfileordirectory"와 같은 파일 작업 문제가 종종 발생합니다.
