用户
 找回密码
 入住 CI 中国社区
搜索
查看: 2798|回复: 1
收起左侧

[讨论/交流] 关于 common.php中 _exception_handler()函数

[复制链接]
发表于 2012-5-11 19:00:28 | 显示全部楼层 |阅读模式
本帖最后由 imwebmaster.net 于 2012-5-11 19:05 编辑

学习CI ,开始读CI的代码,发现PHP基础是那么的重要。一个函数就把我搞晕了。
在CodeIgniter.php 中 我们设置自定义的_exception_handler函数作为异常处理程序

PHP复制代码
 
set_error_handler('_exception_handler');
 
复制代码


该函数位于Common.php中。

PHP复制代码
 
        function _exception_handler($severity, $message, $filepath, $line)
        {
                if ($severity == E_STRICT)
                {
                        return;
                }
                $_error =& load_class('Exceptions', 'core');
 
                if (($severity & error_reporting()) == $severity)
                {
                        $_error->show_php_error($severity, $message, $filepath, $line);
                }
           //略
}
 
 
复制代码


其中 $severity & error_reporting() =?呢? 分析一下

1. $serverity  实为 error_handler  的 errorno

2.  & 为位与操作符  

3. error_reporting([int level]) 可以用来设置错误报告级别,省略参数 则返回当前错误报告级别

当异常发生时, error_handler  被传递到 _exception_handler 函数 ,$severity = errno, 错误报告级别,为整数.

如果ENVIROMENT ='development'(默认) , 那么错误报告级别被设置为 E_ALL .也是整数

那么,$severity & error_reporting() 这个表达式返回什么值,关键在于理解 & 位与操作符
  第一个数值的位第二个数值的位 结果
1
1
1
1
0
0
0
1
0
0
0
0

接下来 先看一下各错误报告级别 常量和值

常量
二进制
E_ERROR 1 0000 0000 0000 0001
E_WARNING 2 0000 0000 0000 0010
E_PARSE 4 0000 0000 0000 0100
E_NOTICE 8 0000 0000 0000 1000
E_CORE_ERROR 16 0000 0000 0001 0000
E_CORE_WARNING 32 0000 0000 0010 0000
E_COMPILE_ERROR 64 0000 0000 0100 0000
E_COMPILE_WARNING 128 0000 0000 1000 0000
E_USER_ERROR 256 0000 0001 0000 0000
E_USER_WARNING 512 0000 0010 0000 0000
E_USER_NOTICE 1024 0000 0100 0000 0000
E_ALL 2047 0000 0111 1111 1111
E_STRICT 2048 0000 1000 0000 0000
(备:表中二进制是16位 的,在实际的情况下可能以32位的来计算)

好吧,首先假设 ($severity & error_reporting()) == $severity  返回TRUE 。

$severity 0000 0*** **** ****
  &  (E_ALL) 0000 0111 1111 1111
结果 0000 0---    ----     -----

按照位与的规则,尝试将* 替换为0或1 ,你是不是发现无论如何 ,结果都是等于$severity

除非$severity 的最高位超出了我用红色标记的最高位,错误级别中,只有E_STRICT菜能做到这一点

$severity0000 1000 0000 000
  &  (E_ALL)0000 0111 1111 1111
结果 0000 0000 0000 0000

$severity = E_STRICT 的情况已经做了处理。

PHP复制代码
 
   if ($severity == E_STRICT)
                {
                        return;
                }
 
复制代码


由此得出一个结论 : 异常错误级别低于 E_ALL时,用$_error->show_php_error来报告错误?。

这条结论建立在初始化设置的错误级别为E_ALL 的基础上,假如不是,这还成立嘛?

$severity0000 0**********
  &  error_reporting()0000 0**********
结果------


回头再看一下 位与操作的那个表。当errot_reporting()不等于E_ALL时候 ,也就是说errot_reporting()不可能每一位都为1 。

这就导致了$severity 中的1对到errot_reporting()的0时 ,该位上就变成了0. 因此 $severity & error_reporting() 的返回值
永远都是 <= $severity 的。那啥时候等于  啥时候小于呢(我快崩溃了)。

看一下错误报告级别 常量和值这张表,不难发现一件事请,错误常量二进制表示中的每一位代表了一种错误级别.如果这位上为1 说明了这个错误级别开启,0则关闭。
---------------
平常,我们使用 位运算符 ! ^ ~ 来设置我们的错误报告级别,实际上就是来操作每个位吧?
比如 error_reporting = E_ERROR | E_PARSE | E_CORE_ERROR
| 位或操作符  对应的位一个为1 结果为1。 真假真嘛
0000 0000 0000 0001
0000 0000 0000 0100
0000 0000 0001 0000
结果 =   0000 0000 0001 0101

-----------

因此 当$severity 的level  不在 error_reporting() 的levels 中 。那么相应位上的1 碰到的永远是0 ,这种情况下 ,$severity & error_reporting() 的返回值 实际上为 0 。

而当$severity 的level 在 error_reporting() 的levels 中。那么相应位上的1碰到的也是1 ,这种情况下$severity & error_reporting() 的返回值 实际上为  $severity 。

结论:异常的level 在 初始设置的 levels 中 异常将 被 $_error->show_php_error。

另外  我查了一下目前PHP错误报告级别 ,发现在 PHP.5.2.X 之后的版本中E_ALL的值已经不等于2047了
32767 in PHP 5.4.x, 30719 in PHP 5.3.x, 6143 in PHP 5.2.x,

但不管如何 新的值各位上依然是1 ,如 32767 =》111111111111111 。遗憾啊,小弟不是计算机专业毕业的,不知道这样的数值 有没有专有的名词啊。我想应该有的吧,谁知道麻烦告诉我一下咯。

另外啊,也不知以上论述有没有问题,有的话,希望大家能积极的指导我一下。



评分

参与人数 1威望 +5 收起 理由
Hex + 5 帖子发的很有水平,顶~

查看全部评分

 楼主| 发表于 2012-5-11 19:03:13 | 显示全部楼层
写着写着 ,我想问的问题是啥来着?搞了一下午 ,真忘了,我晕
好吧,问一下: 是这样的嘛?

本版积分规则