CI加载类源码分析

今天用到CI的library加载,发现同一controller多次load同一library,并期望传入的参数(构造函数接收的参数)生效是不行的,没搞明白,就看了下他的源码

原来CI在load类初始化前,先判断CI这个全局对象已加载的类实例有无已加载过的,若有,便忽略不再加载,期望多次加载的以构造函数构造不同实例自然是不可得。
于是将构造函数修改属性替换为公有方法去操作。

总之,CI加载类只加载一次,不会重复加载,也就像单例模式了,应避免构造传参式修改类属性。

附源码:

在system/loader.php

/**
 * Load class
 *
 * This function loads the requested class.
 *
 * @param    string    the item that is being loaded
 * @param    mixed    any additional parameters
 * @param    string    an optional object name
 * @return    void
 */
protected function _ci_load_class($class, $params = NULL, $object_name = NULL)
{
    // Get the class name, and while we're at it trim any slashes.
    // The directory path can be included as part of the class name,
    // but we don't want a leading slash
    $class = str_replace('.php', '', trim($class, '/'));

    // Was the path included with the class name?
    // We look for a slash to determine this
    $subdir = '';
    if (($last_slash = strrpos($class, '/')) !== FALSE)
    {
        // Extract the path
        $subdir = substr($class, 0, $last_slash + 1);

        // Get the filename from the path
        $class = substr($class, $last_slash + 1);
    }

    // We'll test for both lowercase and capitalized versions of the file name
    foreach (array(ucfirst($class), strtolower($class)) as $class)
    {
        $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';

        // Is this a class extension request?
        if (file_exists($subclass))
        {
            $baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php';

            if ( ! file_exists($baseclass))
            {
                log_message('error', "Unable to load the requested class: ".$class);
                show_error("Unable to load the requested class: ".$class);
            }

            // Safety:  Was the class already loaded by a previous call?
            if (in_array($subclass, $this->_ci_loaded_files))
            {
                // Before we deem this to be a duplicate request, let's see
                // if a custom object name is being supplied.  If so, we'll
                // return a new instance of the object
                if ( ! is_null($object_name))
                {
                    $CI =& get_instance();
                    if ( ! isset($CI->$object_name))
                    {
                        return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
                    }
                }

                $is_duplicate = TRUE;
                log_message('debug', $class." class already loaded. Second attempt ignored.");
                return;
            }

            include_once($baseclass);
            include_once($subclass);
            $this->_ci_loaded_files[] = $subclass;

            return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
        }

        // Lets search for the requested library file and load it.
        $is_duplicate = FALSE;
        foreach ($this->_ci_library_paths as $path)
        {
            $filepath = $path.'libraries/'.$subdir.$class.'.php';

            // Does the file exist?  No?  Bummer...
            if ( ! file_exists($filepath))
            {
                continue;
            }

            // Safety:  Was the class already loaded by a previous call?
            if (in_array($filepath, $this->_ci_loaded_files))
            {
                // Before we deem this to be a duplicate request, let's see
                // if a custom object name is being supplied.  If so, we'll
                // return a new instance of the object
                if ( ! is_null($object_name))
                {
                    $CI =& get_instance();
                    if ( ! isset($CI->$object_name))
                    {
                        return $this->_ci_init_class($class, '', $params, $object_name);
                    }
                }

                $is_duplicate = TRUE;
                log_message('debug', $class." class already loaded. Second attempt ignored.");
                return;
            }

            include_once($filepath);
            $this->_ci_loaded_files[] = $filepath;
            return $this->_ci_init_class($class, '', $params, $object_name);
        }

    } // END FOREACH

    // One last attempt.  Maybe the library is in a subdirectory, but it wasn't specified?
    if ($subdir == '')
    {
        $path = strtolower($class).'/'.$class;
        return $this->_ci_load_class($path, $params);
    }

    // If we got this far we were unable to find the requested class.
    // We do not issue errors if the load call failed due to a duplicate request
    if ($is_duplicate == FALSE)
    {
        log_message('error', "Unable to load the requested class: ".$class);
        show_error("Unable to load the requested class: ".$class);
    }
}
如有疑问,请文末留言交流或邮件:newbvirgil@gmail.com 本文链接 : http://blog.newbmiao.com/2015/01/08/ci-load-class-source-code-analysis.html