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

[已解决] 阅读core/CodeIgniter.php源代码的一处困惑

[复制链接]
发表于 2012-3-16 10:49:53 | 显示全部楼层 |阅读模式
PHP复制代码
        if (method_exists($CI, '_remap'))
        {
                $CI->_remap($method, array_slice($URI->rsegments, 2));
        }
        else
        {
                // is_callable() returns TRUE on some versions of PHP 5 for private and protected
                // methods, so we'll use this workaround for consistent behavior
                if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI))))
                {
                        // Check and see if we are using a 404 override and use it.
                        if ( ! empty($RTR->routes['404_override']))
                        {
                                $x = explode('/', $RTR->routes['404_override']);
                                $class = $x[0];
                                $method = (isset($x[1]) ? $x[1] : 'index');
                                if ( ! class_exists($class))
                                {
                                        if ( ! file_exists(APPPATH.'controllers/'.$class.'.php'))
                                        {
                                                show_404("{$class}/{$method}");
                                        }
 
                                        include_once(APPPATH.'controllers/'.$class.'.php');
                                        unset($CI);
                                        $CI = new $class();
                                }
                        }
                        else
                        {
                                show_404("{$class}/{$method}");
                        }
                }
 
 
复制代码




300多行,为什么先要unset($CI) 再重新实例化一遍?
发表于 2012-3-16 11:13:37 | 显示全部楼层
应该是每次调用的情况都不一样,先销毁在实例化应该会更安全一下吧
(不懂乱说的哈)
发表于 2012-4-3 04:07:44 | 显示全部楼层

因为第一次new 的$class 和第二次new的$class不同了

第一次出现
   $CI = new $class() ;
的地方是 307行左右。此时的$class 是经历过下面代码考验的。
if ( ! class_exists($class)
                OR strncmp($method, '_', 1) == 0
                OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller')))
                )
  这个判断筛选选出来的$class 是已经定义的,并且经过路由解析过来的函数不以 “_”开头,并且函数不在CI_Controller类声明的函数中(index,__construct ,get_instrance).
  所以说白了,第一次$CI = new $class(); 此时实例化的对象$CI 是一个 有效的controller,但是此时不能确定$methon也有效。

第二次出现
$CI = new $class() ;大概346行左右
是在判断$methon是否有效的时候,函数被检验无效了,而你又自定义了404错误页面
                if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($CI))))
                {
                        if ( ! empty($RTR->routes['404_override']))  //设置了自定义的404页面
                        {            
                                $x = explode('/', $RTR->routes['404_override']);
                                $class = $x[0]; //此时的$class 已经不是第一次实例化对象$CI时候的类了
                                $method = (isset($x[1]) ? $x[1] : 'index');
                                if ( ! class_exists($class)) //自定义错误处理页面的controller类没有定义
                                {
                                        if ( ! file_exists(APPPATH.'controllers/'.$class.'.php'))
                                        {
                                                show_404("{$class}/{$method}");
                                        }
                                        include_once(APPPATH.'controllers/'.$class.'.php');
                                        unset($CI); //307行那个由有效的controller实例化的对象$CI,在这里慷慨就义
                                        $CI = new $class();//因为$method无效而创建的$CI被unset了,但是404的页面还要继续,404页面的controller在这里实例化了
   

评分

参与人数 1威望 +5 收起 理由
Hex + 5 赞一个!

查看全部评分

发表于 2013-5-16 13:43:12 | 显示全部楼层
本帖最后由 优雅de凋零 于 2013-5-16 13:56 编辑

第一次new 是 请求的类存在
请求的方法没有与CI_Controller中的方法发生冲突 以及 ...
就new 了
然后的检测是看 方法是否在类中存在
不存在就用 404_override 的处理过程
干掉不存在 请求方法的 类(类存在)

get_class_methods()
里面的参数可以是 类的名称字符串 也可以是 类的实例化对象
什么区别呢???

本版积分规则