phoenixg 发表于 2012-3-16 10:49:53

阅读core/CodeIgniter.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;
                                $method = (isset($x) ? $x : '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) 再重新实例化一遍?

kissgxd 发表于 2012-3-16 11:13:37

应该是每次调用的情况都不一样,先销毁在实例化应该会更安全一下吧
(不懂乱说的哈)

actionbi 发表于 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; //此时的$class 已经不是第一次实例化对象$CI时候的类了
                                $method = (isset($x) ? $x : '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在这里实例化了
   

优雅de凋零 发表于 2013-5-16 13:43:12

本帖最后由 优雅de凋零 于 2013-5-16 13:56 编辑

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

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

页: [1]
查看完整版本: 阅读core/CodeIgniter.php源代码的一处困惑