zblogphp系统文件说明c_system_debug.php错误调试

admin2023-01-191019

此内容是对文件 zblogphp1.5.1\zb_system\function\c_system_debug.php 的代码分析,建议打开此文件对照阅读。

该文件包含以下6个函数以及一个类,如下:

function Debug_PrintGlobals 显示全局变量

function Debug_PrintIncludefiles 打印全局Include文件

function Debug_PrintConstants 打印全局自定义常量

function Debug_Error_Handler 错误调度提示

function Debug_Exception_Handler 异常处理

function Debug_Shutdown_Handler 当机错误处理

class ZBlogException 异常处理类

首先讲解异常处理类,位于该文件第238行处。

类的开头定义私有静态变量 $_zbe = null,$_isdisable = null (类实例和是否禁用调度标识)

定义公共静态变量

$isdisable = false 是否禁用调度

$isstrict = false 是否严格调度模式

$iswarning = true 是否警告调度模式

$error_id = 0 错误ID

$error_file = null 错误文件

$error_line = null 错误行

$islogerror = false 是否写入错误日志

定义公共变量 $type(错误类型/错误级别,如下17中错误类型,) $message(错误信息) $messagefull(完整的错误信息,会输出是什么地方出错的) $file(错误文件) $line(错误行) 和数组 $errarray = array()(错误说明数组)

构造函数 __construct() 会在实例化该类时自动调用初始化错误数组列表

$this->errarray 详细信息如下:

0:UNKNOWN 未知错误

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 启用PHP对代码的修改建议,以确保代码具有最佳的互操作性和向前兼容性

4096:E_RECOVERABLE_ERROR 可被捕捉的致命错误

8192:E_DEPRECATED 运行时通知

16384:E_USER_DEPRECATED 用户产生的警告信息

30719:E_ALL E_STRICT除外的所有错误和警告信息

类函数 __get($name) 获取参数,(暂时没有找到更多信息,从代码看是返回$this->errarray的错误级别)

该函数首先判断参数是否为 typeName 字符串,如果不是则不执行,然后根据错误级别来返回错误级别的字符串说明。

类函数 GetInstance() 获得单一实例,实例化异常处理类

根据 $_zbe 是否定义来进行实例,外部使用 ZBlogException::GetInstance() 进行实例化该类。

静态类函数 SetErrorHook() 设置错误处理函数,该函数执行了下面3个处理

设置错误处理函数由 Debug_Error_Handler 函数处理

设置异常处理函数由 Debug_Exception_Handler 函数处理

注册一个函数,这个函数会在PHP执行完成后执行,这里这个函数是 Debug_Shutdown_Handler

静态类函数 ClearErrorHook() 清除注册的错误处理函数,这个函数主要执行下面的3个操作

create_function创建匿名函数,参数为空。返回值设置为 false 后,则因为这个函数不处理任何事情且返回false,这会让标准的错误处理程序继续调用。起到清除之前设置的处理函数。下面两个同理。

静态类函数 EnableErrorHook() 启用错误调度

该函数设置 $isdisable 变量为 false,启用错误处理标记

静态类函数 DisableErrorHook() 禁止错误调度

该函数设置 $isdisable 变量为 true,关闭错误处理标记

静态类函数 SuspendErrorHook() 暂停错误调度

静态类函数 ResumeErrorHook() 恢复错误调度

两个函数都是首先判断 self::$_isdisable 的私有标记与 null 的全比较

暂停错误调度函数是不全等跳出,恢复错误调度函数是全等跳出

然后设置 $isdisable 和 $_isdisable 的状态

理解:启用调度后,$isdisable = false,$_isdisable = null,这时执行恢复调度会直接return,只能执行暂停调度

执行暂停调度后,$_isdisable会更改为false或者true,$isdisable设置为true禁止调度!

这时因为$_isdisable不等于null,所以此时只能执行恢复调度函数而无法再次执行暂停调度。

执行恢复调度会再次设置$_isdisable为null,$isdisable设置为调度状态。

总结:调度状态只能先暂停,才能执行恢复。反之不行。

以下4个函数分别设置调度状态级别

静态类函数 DisableStrict() 禁用严格模式

静态类函数 EnableStrict() 打开严格模式

静态类函数 DisableWarning() 禁用警告

静态类函数 EnableWarning() 打开警告

静态类函数 Trace($s) 日志跟踪

调用位于 c_system_common.php 文件中的 Logs 函数 进行记录日志操作,内容为参数。Logs函数不在此处展开。

类函数 ParseError($type, $message, $file, $line) 解析错误信息

参数为:错误级别,内容,文件,行。

该函数只做了一件事情就是对 $type,$message,$messagefull,$file,$line进行了赋值操作。

$messagefull变量额外添加字符串 ‘(set_error_handler)’。说明是错误调度捕捉的错误,这个函数只会在错误调度函数执行,而错误调度函数是被SetErrorHook() 函数设置的错误处理函数。

同理

类函数 ParseShutdown($error) 解析当机错误处理,参数是一个数组

类函数 ParseException($exception) 解析异常处理,参数有 异常处理函数 Debug_Exception_Handler 获取并传递,$exception 是PHP抛出的异常对象,在PHP7以上是Throwable。这里只讨论exception

$exception对象包含属性

string $message 异常消息内容

int $code 异常代码

string $file 抛出异常的文件名

int $line 抛出异常在该文件中的行号

$exception对象包含方法

string getMessage() 获取异常消息内容

Throwable getPrevious() 返回异常链中的前一个异常

int getCode()  获取异常代码

string getFile() 创建异常时的程序文件名称

int getLine() 获取创建的异常所在文件中的行号

array getTrace() 获取异常追踪信息

string getTraceAsString() 获取字符串类型的异常追踪信息

string __toString() 将异常对象转换为字符串

void __clone() 异常克隆

这里使用了

$exception->getMessage() 异常消息内容

$exception->getCode() 异常代码

$exception->getFile() 异常时的程序文件名称

$exception->getLine() 异常所在文件中的行

然后判断 异常类的 $error_file 是否有值(是否不等于null),如果是则这个值赋值给 $this->file

同样判断 self::$error_line 不全等于 null,将值赋值给 $this->line。

类函数 Display() 输出错误信息

使用函数 headers_sent() 判断 HTTP 标头是否已被发送以及在哪里被发送,如果没有,执行位于 c_system_common.php文件的 Http500() 函数。清空(擦掉)输出缓冲区。

$error = $this 将类本身赋值到 $error。

执行 挂载在 Filter_Plugin_Debug_Display 插件中的函数

加载 zblogphp1.5.1\zb_system\defend\error.php 页面,显示错误信息页面

执行 RunTime() 函数显示页面执行时间

//``flush()`` and ``exit($errorCode)`` is for HHVM

//https://github.com/zblogcn/zblogphp/issues/32

flush() 函数刷新输出缓冲

exit(1) 退出

类函数 get_code($file, $line) 获取出错代码信息

参数:错误的文件名和行号

如果 $file 值是 Unknown,返回空数组

如果 指定的$file文件名不可读,返回空数组

array_slice函数根据条件从数组中取一段值

file($file) 把整个文件读入一个数组,文件中的每一行都是数组的某一个元素

max(0, $line - 5) 函数返回两个数的最大值,这里表示如果参数行小于5,则返回0

array_slice 第三个参数表示需要获取的行数

array_slice 第四个参数表示是否重新排序并重置数组的数字索引。这里用TRUE来阻止这个行为

所以 $aFile = array_slice(file($file), max(0, $line - 5), 10, true);

的结果为获得出错文件以错误所在行前5行开始起的10行的内容数组。

然后 foreach 将每一行的字符串使用 htmlspecialchars 将特殊字符转换为 HTML 实体

源代码为:

foreach ($aFile as &$sData) {

//&$ = ByRef

$sData = htmlspecialchars($sData);

}

最后 return $aFile;,总之我看不懂 $aFile as &$sData 这个是什么意思,是将 $aFile 每个元素追加到 $sData?

类函数 possible_causes_of_the_error() 得到可能的错误原因

global $lang 全局公共语言数组

global $bloghost 当前网站地址

$result = '' 返回结果

如果 ZBlogException::$error_id 错误ID不等于0,表示是Z-BlogPHP自身抛出的错误

然后在判断 $lang['error_reasons'][ZBlogException::$error_id] 指定的ID值是否定义,如果定义,将对应结果(什么系统的哪哪哪错了,环境啊,权限啊什么的)赋值给 $result

否则将默认错误(空)赋值给$result

然后$lowerErrorReason = strtolower($this->message); strtolower函数将所有字符转换为小写并赋值$this->message是错误信息。上面说过。

foreach ($lang['error_reasons']['other'] as $key => $value) 判断语言包中其他数组中的各个数组元素,看看$lowerErrorReason的值是不是和这里的错误字符串一样,如果一样,将对应值赋值到$result

$errorId = urlencode(ZBlogException::$error_id); 得到错误ID URL编码后赋值

$errorMessage = urlencode($this->message); 得到错误信息URL编码后赋值

$moreHelp = $lang['offical_urls']['more_help']; 获得语言包中的该值,是一个在线帮助链接

$moreHelp = str_replace('{%id%}', $errorId, $moreHelp); 将该链接的对应字符替换为实际ID值

$moreHelp = str_replace('{%message%}', $errorMessage, $moreHelp); 同上

$result .= $lang['error_reasons']['end']; 拼接语言包中的对应内容

$result = str_replace('{%bloghost%}', $bloghost, $result); 继续替换

$result = str_replace('{%morehelp%}', $moreHelp, $result); 继续替换

返回结果。

这个函数的执行结果是:

第一段,哪里错了,哪里权限有问题。

第二段,如果你是访客,请联系站长,如果你是站长,什么什么。

异常类代码解读完毕,讲解这个文件中的几个函数,这几个函数可以在任意文件中使用。

函数 Debug_PrintGlobals() 显示全局变量

说明:使用 foreach 函数来获取 $GLOBALS 的所有内容,返回一个数组吧。

函数 Debug_PrintIncludefiles() 打印全局include文件

说明:使用 foreach 函数通过 get_included_files() 来获取数据,返回一个数组

函数 Debug_PrintConstants() 打印全局自定义常量

说明:函数 get_defined_constants 获得所有常量的关联数组,键是常量名,值是常量值

这里只获取 user的子健内容,所以使用

if (isset($a['user'])) {

$a = $a['user'];

}

获得,,返回一个数组

上面这三个函数都是只应用在了查看 phpinfo 信息的页面里。

函数 Debug_Error_Handler($errno, $errstr, $errfile, $errline) 错误调度提示

改函数4个参数分别是错误级别,错误信息,错误文件名,错误行

1.首先判断错误调度是否关闭,如果是则直接return。 ZBlogException::$isdisable == true

2.然后 执行挂载到 Filter_Plugin_Debug_Handler 钩子上的插件函数

3.然后对 $_SERVER['_error_count'] 的服务器指示错误次数变量值加1

4.判断是否写入错误日志,如果写入的话调用 Logs 函数执行写入操作 ZBlogException::$islogerror == true

var_export的第二个参数设置为true将数组的各个元素值以字符串拼接后写入文件,Logs函数第二个参数true表示这个一个error日志。

5.判断给定的文件名是否可读,如果可以读取的话,获取错误行的前一行信息

reset 将数组内部指针倒回到第一个单元并返回第一个数组单元的值

判断该行有没有 @ 符号,如果没有则 return (这里为什么要return?)

6.如果关闭警告,则错误级别是警告级别的话直接return。

7.如果关闭严格模式,则对 E_STRICT E_NOTICE E_USER_NOTICE 级别(建议,运行时通知,用户产生的通知信息)直接 return。

//屏蔽屏蔽系统的错误,防ZBP报系统的错误,不过也有可能导致ZBP内的DEPRECATED错误也被屏蔽了

8.如果错误级别是 E_CORE_WARNING (警告性)直接返回return

9.如果错误级别是 E_COMPILE_WARNING (警告性)直接返回return

10.如果常量 E_DEPRECATED 已经定义且错误级别是 E_DEPRECATED (运行时通知)直接返回return

11.如果常量 E_USER_DEPRECATED 已经定义且错误级别是 E_USER_DEPRECATED (用户产生的警告信息)直接返回return

下面的就是 用户产生的错误信息 和 可被扑捉的致命错误 了

首先 $zbe = ZBlogException::GetInstance(); 获得唯一异常处理类实例

然后 $zbe->ParseError($errno, $errstr, $errfile, $errline); 解析错误信息

最后 $zbe->Display(); 输出错误信息

函数 Debug_Exception_Handler($exception) 异常处理

1.首先判断错误调度是否关闭,如果是则直接return。 ZBlogException::$isdisable == true

2.然后 执行挂载到 Filter_Plugin_Debug_Handler 钩子上的插件函数

3.然后对 $_SERVER['_error_count'] 的服务器指示错误次数变量值加1

4.判断是否写入错误日志,如果写入的话调用 Logs 函数执行写入操作 ZBlogException::$islogerror == true

var_export的第二个参数设置为true将数组的各个元素值以字符串拼接后写入文件,Logs函数第二个参数true表示这个一个error日志。

5.$zbe = ZBlogException::GetInstance(); 获得唯一异常处理类实例

6.$zbe->ParseException($exception); 解析异常处理

7.$zbe->Display(); 输出错误信息

函数 Debug_Shutdown_Handler() 当机错误处理

首先使用 error_get_last函数获取最后一个发生的错误的信息,如果没有,返回NULL,不执行该函数。

如果获取到了错误信息

1.判断错误调度是否关闭,如果是则直接return。

2.然后 执行挂载到 Filter_Plugin_Debug_Handler 钩子上的插件函数

3.然后对 $_SERVER['_error_count'] 的服务器指示错误次数变量值加1

4.判断是否写入错误日志,如果写入的话调用 Logs 函数执行写入操作 ZBlogException::$islogerror == true

var_export的第二个参数设置为true将数组的各个元素值以字符串拼接后写入文件,Logs函数第二个参数true表示这个一个error日志。

5.如果关闭警告,则错误级别是警告级别的话直接return。

6.如果关闭严格模式,则对 E_STRICT E_NOTICE E_USER_NOTICE 级别(建议,运行时通知,用户产生的通知信息)直接 return。

7.如果错误级别是 E_CORE_WARNING (警告性)直接返回return

8.如果错误级别是 E_COMPILE_WARNING (警告性)直接返回return

9.如果常量 E_DEPRECATED 已经定义且错误级别是 E_DEPRECATED (运行时通知)直接返回return

10.如果常量 E_USER_DEPRECATED 已经定义且错误级别是 E_USER_DEPRECATED (用户产生的警告信息)直接返回return

最后

$zbe = ZBlogException::GetInstance(); 获得唯一异常处理类实例

$zbe->ParseShutdown($error); 解析当机错误处理

$zbe->Display(); 输出错误信息

网友评论