analyzer 发表于 2008-9-23 01:22:40

分析CI的错误处理(404等)

前些天群里有位朋友询问关于CI如何设置404的问题,晚上仔细研究了一下CI的异常处理模块,现总结如下:
大家都知道CI处理错误的函数有三个,分别是:show_error('消息')、show_404('页面')
和log_message('级别','消息')。[*]CI处理异常的流程:       首先,CI在codeigniter.php的38行处加载common文件
       require(BASEPATH.'codeigniter/Common'.EXT);
       我们试着分析一下Common.php文件,此文件的187行开始,直到文档末尾,定义了错误处理函数。

function show_error($message)
{
//调用异常处理文件
      $error =& load_class('Exceptions');
//异常处理文件中的show_error函数
      echo $error->show_error('An Error Was Encountered', $message);
      exit;
}

function show_404($page = '')
{
//调用异常处理文件
$error =& load_class('Exceptions');
//异常处理文件中的show_404函数
$error->show_404($page);
exit;
}

function log_message($level = 'error', $message, $php_error = FALSE)
{
static $LOG;
//获取CI配置项
$config =& get_config();
if ($config['log_threshold'] == 0)
{
return;
}
//调用log.php类文件
$LOG =& load_class('Log');
//log.php类文件中的write_log函数
$LOG->write_log($level, $message, $php_error);
}


从以上代码中,我们可以发现,CI的这些错误处理函数都调用了同一个文件,那就是Exceptions.php,这个文件位于/system/library/目录下,接下来,我们就分析一下这个文件

function show_404($page = '')

function show_404($page = '')
//404处理页面
{
//定义两个变量
$heading = "404 Page Not Found";
$message = "The page you requested was not found.";
//写入日志
log_message('error', '404 Page Not Found --> '.$page);
//调用show_error函数,并将之前定义的$heading和$message变量传递过去
//这句中的第三个参数是关键error_404,这是模板文件名
//如果想更改,就得更改这个参数,我们可以把error_404替换为你的模板文件,或者将它变为
//echo $this->show_error($heading, $message,$page);
//这个$page为模板文件名
echo $this->show_error($heading, $message, 'error_404');
exit;
}


function show_error($heading, $message, $template = 'error_general')

//这才是异常处理的核心
function show_error($heading, $message, $template = 'error_general')
{
//简单过滤一下传递过来的变量的值
$message = '<p>'.implode('</p><p>', ( ! is_array($message)) ? array($message) : $message).'</p>';
if (ob_get_level() > $this->ob_level + 1)
{
   ob_end_flush();
}
ob_start();
//这里就是模板文件,注意:CI所有的异常处理模板文件都在errors目录下
include(APPPATH.'errors/'.$template.EXT);
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}


function show_php_error($severity, $message, $filepath, $line)

//这个函数和上面的函数大体差不多
function show_php_error($severity, $message, $filepath, $line)
{
$severity = ( ! isset($this->levels[$severity])) ? $severity : $this->levels[$severity];

$filepath = str_replace("\\", "/", $filepath);

// For safety reasons we do not show the full file path
if (FALSE !== strpos($filepath, '/'))
{
   $x = explode('/', $filepath);
   $filepath = $x.'/'.end($x);
}

if (ob_get_level() > $this->ob_level + 1)
{
   ob_end_flush();
}
ob_start();
include(APPPATH.'errors/error_php'.EXT);
$buffer = ob_get_contents();
ob_end_clean();
echo $buffer;
}


最后附上我更改后的show_error函数

function show_404($page = '')
{
$heading = "404 Page Not Found";
$message = "The page you requested was not found.";
log_message('error', '404 Page Not Found --> '.$page);
if(!$page) {
//如果$page为空,则显示默认404错误页面
   echo $this->show_error($heading, $message, 'error_404');
}
else {
//如果$page不为空,则显示定义的404错误页面
   echo $this->show_error($heading, $message, $page);
}
exit;
}

关于调用:
调用时可以这样:show_404()或show_404('404')

这个修改方法同样适用于show_error函数,我们看一下修改后的show_error函数:

function show_error($heading, $message, $template = '')
{
$message = '<p>'.implode('</p><p>', ( ! is_array($message)) ? array($message) : $message).'</p>';
if (ob_get_level() > $this->ob_level + 1)
{
   ob_end_flush();
}
if(!$template) {
   $template='error_general';
}
ob_start();
include(APPPATH.'errors/'.$template.EXT);
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
}



而调用函数也相应得变为
log_message('级别', '消息','模板')注意:第三个参数可为空

大体就是这样,如果我的分析有错误,请各位网友跟贴指正,谢谢

[ 本帖最后由 analyzer 于 2008-9-23 02:17 编辑 ]

yz20sui 发表于 2008-9-23 01:53:51

学习一下:loveliness:

kissmumu 发表于 2008-9-23 08:43:21

对CI比较深入了,研究源码了。支持一下。

Hex 发表于 2008-9-23 10:09:37

这么好的教程一定要加分 加精

wtm_mac 发表于 2008-9-23 13:42:24

干的好,伙计:):lol

a123123 发表于 2010-7-13 08:27:36

:)顶一下

mengjian 发表于 2010-8-25 15:51:28

好教程,顶顶顶...

guiyintianyuan 发表于 2011-9-20 10:36:06

很好的教程!不过为什么logs的文件夹改不过来属性呢?一直是只读?
页: [1]
查看完整版本: 分析CI的错误处理(404等)