CI框架源码学习笔记6——Config.php

接着上一节往下,我们这一节来看看配置类Config.php,对应手册内容http://codeigniter.org.cn/user_guide/libraries/config.html。

class CI_Config {

    //所有已经加载的配置项组成的数组
    public $config = array();

    //所有已经加载的配置文件组成的数组
    public $is_loaded =    array();

    //用来搜索配置文件的路径数组
    public $_config_paths =    array(APPPATH);

    // --------------------------------------------------------------------

    public function __construct()
    {
        //加载主配置文件config.php
        $this->config =& get_config();

        //如果配置中没有base_url提供的话,设置base_url
        if (empty($this->config[‘base_url‘]))
        {
            //当前运行脚本所在的服务器的IP地址,设置base_url
            if (isset($_SERVER[‘SERVER_ADDR‘]))
            {
                if (strpos($_SERVER[‘SERVER_ADDR‘], ‘:‘) !== FALSE)
                {
                    $server_addr = ‘[‘.$_SERVER[‘SERVER_ADDR‘].‘]‘;
                }
                else
                {
                    $server_addr = $_SERVER[‘SERVER_ADDR‘];
                }

                $base_url = (is_https() ? ‘https‘ : ‘http‘).‘://‘.$server_addr
                    .substr($_SERVER[‘SCRIPT_NAME‘], 0, strpos($_SERVER[‘SCRIPT_NAME‘], basename($_SERVER[‘SCRIPT_FILENAME‘])));
            }
            else
            {
                $base_url = ‘http://localhost/‘;
            }
            //调用set_item方法来设置base_url到配置中
            $this->set_item(‘base_url‘, $base_url);
        }
        //日志记录,需要开启到对应日志等级
        log_message(‘info‘, ‘Config Class Initialized‘);
    }

    // --------------------------------------------------------------------

    public function load($file = ‘‘, $use_sections = FALSE, $fail_gracefully = FALSE)
    {
        //$file为空时设置默认值config;替换参数中的.php后缀为空
        $file = ($file === ‘‘) ? ‘config‘ : str_replace(‘.php‘, ‘‘, $file);
        //$loaded用来作为最后返回的结果值
        $loaded = FALSE;

        //从路径数组循环
        foreach ($this->_config_paths as $path)
        {
            //循环文件名称
            foreach (array($file, ENVIRONMENT.DIRECTORY_SEPARATOR.$file) as $location)
            {
                //拼接完整的文件路径
                $file_path = $path.‘config/‘.$location.‘.php‘;
                //判断配置文件是否已經加载过,若加载过直接返回true
                if (in_array($file_path, $this->is_loaded, TRUE))
                {
                    return TRUE;
                }
                //判断文件是否存在,若不存在跳出当前的循环
                if ( ! file_exists($file_path))
                {
                    continue;
                }

                //引入文件
                include($file_path);

                //判断文件中是否设置了$config变量,并且$config变量是否是数组
                //若不是,根据$fail_gracefully执行返回false或者输出错误信息
                if ( ! isset($config) OR ! is_array($config))
                {
                    if ($fail_gracefully === TRUE)
                    {
                        return FALSE;
                    }

                    show_error(‘Your ‘.$file_path.‘ file does not appear to contain a valid configuration array.‘);
                }

                //根据参数$use_sections,判断每个配置文件中的配置是否需要被存储到以该配置文件名为索引的数组中
                if ($use_sections === TRUE)
                {
                    $this->config[$file] = isset($this->config[$file])
                        ? array_merge($this->config[$file], $config)
                        : $config;
                }
                else
                {
                    $this->config = array_merge($this->config, $config);
                }

                //将当前加载的文件,加载到数组$this->is_loaded
                $this->is_loaded[] = $file_path;
                //设置$config为null,用于下次循环判断
                $config = NULL;
                //加载成功后设置$loaded为true
                $loaded = TRUE;
                //记录debug日志
                log_message(‘debug‘, ‘Config file loaded: ‘.$file_path);
            }
        }

        //根据$loaded返回true或者false
        if ($loaded === TRUE)
        {
            return TRUE;
        }
        elseif ($fail_gracefully === TRUE)
        {
            return FALSE;
        }

        //$fail_gracefully设置为false是会打印错误信息,倘若有错误的话
        show_error(‘The configuration file ‘.$file.‘.php does not exist.‘);
    }

    // --------------------------------------------------------------------

    //获取配置内容
    //如果你在使用 $this->config->load 方法时使用了第二个参数,每个配置文件中的配置 被存储到以该配置文件名为索引的数组中
    //要获取该配置项,你可以将 $this->config->item() 方法的第二个参数设置为这个索引名(也就是配置文件名)
    public function item($item, $index = ‘‘)
    {
        //$index为空的时候
        //倘若查询的配置存在,那么直接返回数组内容,否则返回null
        if ($index == ‘‘)
        {
            return isset($this->config[$item]) ? $this->config[$item] : NULL;
        }

        //返回某个文件中的对应配置内容
        return isset($this->config[$index], $this->config[$index][$item]) ? $this->config[$index][$item] : NULL;
    }

    // --------------------------------------------------------------------

    //这个方法和 item() 一样,只是在获取的配置项后面添加一个斜线,如果配置项不存在,返回 NULL
    public function slash_item($item)
    {
        if ( ! isset($this->config[$item]))
        {
            return NULL;
        }
        elseif (trim($this->config[$item]) === ‘‘)
        {
            return ‘‘;
        }

        return rtrim($this->config[$item], ‘/‘).‘/‘;
    }

    // --------------------------------------------------------------------

    //该方法返回你的网站的 URL ,包括你在配置文件中设置的 "index" 值。
    //这个方法通常通过 URL 辅助函数 中函数来访问。
    public function site_url($uri = ‘‘, $protocol = NULL)
    {
        //获取站点根url
        $base_url = $this->slash_item(‘base_url‘);

        //$protocol一般用作协议,例如http或者https
        if (isset($protocol))
        {
            //如果$protocol为空,截取base_url双斜杠之后的部分
            if ($protocol === ‘‘)
            {
                $base_url = substr($base_url, strpos($base_url, ‘//‘));
            }
            //否则截取冒号之后的部分,与$protocol拼接
            else
            {
                $base_url = $protocol.substr($base_url, strpos($base_url, ‘://‘));
            }
        }

        //如果没有提供参数$uri,后面跟上配置index_page,然后直接返回
        if (empty($uri))
        {
            return $base_url.$this->item(‘index_page‘);
        }

        //如果参数存在,返回格式化之后的字符串
        $uri = $this->_uri_string($uri);

        //根据配置enable_query_strings判断是否需要添加后缀
        if ($this->item(‘enable_query_strings‘) === FALSE)
        {
            //获取后缀的值
            $suffix = isset($this->config[‘url_suffix‘]) ? $this->config[‘url_suffix‘] : ‘‘;

            //后缀值不为空的时候
            if ($suffix !== ‘‘)
            {
                //判断$uri中是否存在?,如果存在那么在?前添加后缀,否则在最后添加后缀
                if (($offset = strpos($uri, ‘?‘)) !== FALSE)
                {
                    $uri = substr($uri, 0, $offset).$suffix.substr($uri, $offset);
                }
                else
                {
                    $uri .= $suffix;
                }
            }

            return $base_url.$this->slash_item(‘index_page‘).$uri;
        }
        //配置enable_query_strings没有开启,并且$uri中没有?时,在它的前面加上?
        elseif (strpos($uri, ‘?‘) === FALSE)
        {
            $uri = ‘?‘.$uri;
        }

        //返回最后构成的url
        return $base_url.$this->item(‘index_page‘).$uri;
    }

    // -------------------------------------------------------------

    //获取base_url,这里跟上面方法的区别就是没有带默认的index_page和后缀的操作
    public function base_url($uri = ‘‘, $protocol = NULL)
    {
        $base_url = $this->slash_item(‘base_url‘);

        if (isset($protocol))
        {
            // For protocol-relative links
            if ($protocol === ‘‘)
            {
                $base_url = substr($base_url, strpos($base_url, ‘//‘));
            }
            else
            {
                $base_url = $protocol.substr($base_url, strpos($base_url, ‘://‘));
            }
        }

        return $base_url.$this->_uri_string($uri);
    }

    // -------------------------------------------------------------

    //跟时化参数成指定形式字符串的方法
    protected function _uri_string($uri)
    {
        //enable_query_strings没有开启时我们返回的是/分割的字符串,较为美观
        if ($this->item(‘enable_query_strings‘) === FALSE)
        {
            is_array($uri) && $uri = implode(‘/‘, $uri);
            return ltrim($uri, ‘/‘);
        }
        //配置开启是返回的是URL-encode 之后的请求字符串
        elseif (is_array($uri))
        {
            return http_build_query($uri);
        }

        return $uri;
    }

    // --------------------------------------------------------------------

    //返回系统路径,废弃方法,因为暴露系统路径是不安全的
    public function system_url()
    {
        $x = explode(‘/‘, preg_replace(‘|/*(.+?)/*$|‘, ‘\\1‘, BASEPATH));
        return $this->slash_item(‘base_url‘).end($x).‘/‘;
    }

    // --------------------------------------------------------------------

    //设置某个配置项的值
    public function set_item($item, $value)
    {
        $this->config[$item] = $value;
    }

}

Config.php文件中的不是很复杂,主要提供了记载和获取配置文件内容的功能,以及常用url的获取。

时间: 2024-10-05 05:07:45

CI框架源码学习笔记6——Config.php的相关文章

PHP框架CodeIgniter CI框架源码学习笔记-index.php一切的入口

CI框架(CodeIgniter)的基本执行流程图以备参考: index.php作为CI框架的入口文件,源码阅读,自然由此开始.

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

CI框架源码阅读笔记2 一切的入口 index.php

上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里这次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现. 1.       设置应用程序环境 define('ENVIRONMENT', 'development'); 这里的development可以是任何你喜欢的环境名称(比如dev,再如test),相对应的,你要在下面的switch case代码块中

CI框架源码阅读笔记4 引导文件CodeIgniter.php

到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.com/usr/reg 经过引导文件,实际上会交给Application中的UsrController控制器的reg方法去处理. 这之中,CodeIgniter.php做了哪些工作?我们一步步来看. 1.    导入预定义常量.框架环境初始化 之前的一篇博客(CI框架源码阅读笔记2 一切的入

CI框架源码阅读笔记5 基准测试 BenchMark.php

上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功能,各模块之间可以相互调用,共同构成了CI的核心骨架. 从本篇开始,将进一步去分析各组件的实现细节,深入CI核心的黑盒内部(研究之后,其实就应该是白盒了,仅仅对于应用来说,它应该算是黑盒),从而更好的去认识.把握这个框架. 按照惯例,在开始之前,我们贴上CI中不完全的核心组件图: 由于BenchMa

CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程

最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动.最近项目少,总算是有了一些时间去写一些东西.于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时刻提醒自己:借鉴和学习才有出路,忘记过去意味着背叛! 基本术语说明 在本文开始之前,有必要对文中反复出现的术语做一个简单的说明,如果你对这一部分已经熟谙,完全可以略过.本文中反复出现和提及的术语包括: 前端控制器(Front Controller): 用于集中控制用户的所有请求的组件,将用户的请求发

****CI框架源码阅读笔记7 配置管理组件 Config.php

http://blog.csdn.net/ohmygirl/article/details/41041597 一个灵活可控的应用程序中,必然会存在大量的可控参数(我们称为配置),例如在CI的主配置文件中(这里指Application/Config/Config.php文件),有如下多项配置: $config['base_url'] = 'http://test.xq.com'; $config['index_page'] = ''; $config['uri_protocol'] = 'AUTO

CI框架源码阅读笔记9 CI的自动加载机制autoload

本篇并不是对某一组件的详细源码分析,而只是简单的跟踪了下CI的autoload的基本流程.因此,可以看做是Loader组件的分析前提. CI框架中,允许你配置autoload数组,这样,在你的应用程序初始化时,会自动加载相应的类库,例如,在application/config/autoload.php中,autoload的配置如下: $autoload['libraries'] = array("smarty", "redis"); 则CI框架初始化时,会自动加载l

CI框架源码阅读笔记6 扩展钩子 Hook.php

CI框架允许你在不修改系统核心代码的基础上添加或者更改系统的核心功能(如重写缓存.输出等).例如,在系统开启hook的条件下(config.php中$config['enable_hooks'] = TRUE;),通过添加特定的钩子,可以让系统在特定的时刻触发特定的脚本: $hook['post_system'] = array( 'class' => 'frameLog', 'function' => 'postLog', 'filename' => 'post_system.php'