日期:2014-05-17  浏览次数:20409 次

ThinkPHP源码分析系列—错误处理

ThinkPHP有一个全局函数halt专门用来对错误进行格式化输出显示,可以在系统 函数库中找到它。通过这个函数,可以保证应用程序错误处理的一致性。


先把代码贴上来:

function halt($error) {
    if (IS_CLI)
        exit($error);
    $e = array();
    if (C('APP_DEBUG')) {
        //调试模式下输出错误信息
        if (!is_array($error)) {
            $trace = debug_backtrace();  // 返回多维数组
            $e['message'] = $error;
            $e['file'] = $trace[0]['file'];
            $e['class'] = $trace[0]['class'];
            $e['function'] = $trace[0]['function'];
            $e['line'] = $trace[0]['line'];
            $traceInfo = '';
            $time = date("y-m-d H:i:m", $_SERVER["REQUEST_TIME"]);
            foreach ($trace as $t) {
                $traceInfo .= '[' . $time . '] ' . $t['file'] . ' (' . $t['line'] . ') ';
                $traceInfo .= $t['class'] . $t['type'] . $t['function'] . '(';
                $traceInfo .= implode(', ', $t['args']);
                $traceInfo .= ")<br/>";
            }
            $e['trace'] = $traceInfo;
        } else {
            $e = $error;
        }
        // 包含异常页面模板
        include C('TMPL_EXCEPTION_FILE');
    } else {
        //否则定向到错误页面
        $error_page = C('ERROR_PAGE');
        if (!empty($error_page)) {
            redirect($error_page);	// 自定义错误页面
        } else {
            if (C('SHOW_ERROR_MSG'))
                $e['message'] = is_array($error) ? $error['message'] : $error;
            else
                $e['message'] = C('ERROR_MESSAGE');
            // 包含异常页面模板
            include C('TMPL_EXCEPTION_FILE');
        }
    }
    exit;  // 发生错误时,退出程序
}

?

halt函数首先会检查PHP的SAPI(服务器端应用编程接口),如果为CLI方式,则直接退出程序。目前流行的方式是PHP作为一个模块被加载到Apache中,这个时候PHP的SAPI为apache2handler。ThinkPHP为方便应用程序的开发,提供了一套调试机制。当处于开发阶段时,可以开启调试机制,方便查错。而在部署环境阶段 时,则关闭调试机制,提高应用的效率和安全性。在这两种情况下,错误处理也是不同的。


当开启调试机制时,如果传递的错误数据信息不是以数组形式存储的,则将PHP内置回溯函数debug_backtrace处理的数据存储在一数组中,其中包括错误信息,文件名,类和函数等数据。如果传递的错误数据信息是以数组形式存储的,则为该数组建立索引即可。最后通过配置的异常页面模板格式化显示错误信息,默认异常页面模板放在框架模板目录下,关键内容贴在这里:

<div class="notice">
<h2>系统发生错误 </h2>
<div >您可以选择 [ <A HREF="<?php echo($_SERVER['PHP_SELF'])?>">重试</A> ] [ <A HREF="javascript:history.back()">返回</A> ] 或者 [ <A HREF="<?php echo(__APP__);?>">回到首页</A> ]</div>
<?php if(isset($e['file'])) {?>
<p><strong>错误位置:</strong> FILE: <span class="red"><?php echo $e['file'] ;?></span> LINE: <span class="red"><?php echo $e['line'];?></span></p>
<?php }?>
<p class="title">[ 错误信息 ]</p>
<p class="message"><?php echo $e['message'];?></p>
<?php if(isset($e['trace'])) {?>
<p class="title">[ TRACE ]</p>
<p id="trace">
<?php echo nl2br($e['trace']);?>
</p>
<?php }?>
</div>

?

当关闭调试机制时,也就是在生产环境中,可以自定义错误页面显示。如果系统找不到自定义错误显示模板,则会渲染上面的异常页面模板。

?

(完)