1 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 2 3 // ------------------------------------------------------------------------ 4 5 /** 6 * CodeIgniter Config Class 7 */ 8 class CI_Config { 9 10 /** 11 * List of all loaded config values 12 */ 13 var $config = array(); 14 15 16 /** 17 * List of all loaded config files 18 */ 19 var $is_loaded = array(); 20 21 22 /** 23 * List of paths to search when trying to load a config file 24 */ 25 var $_config_paths = array(APPPATH); 26 27 /** 28 * Constructor 29 */ 30 function __construct() 31 { 32 $this->config =& get_config(); 33 log_message('debug', "Config Class Initialized"); 34 35 //在config/config.php里面有个配置项是base_url,它并不是必须配置项,如果没有配置,则系统就在这个地方 36 //自己去它进行赋值。 37 if ($this->config['base_url'] == '') 38 { 39 //一般来说,如果通过http访问网站的话,这个值都会有的。 40 if (isset($_SERVER['HTTP_HOST'])) 41 { 42 //判断是否通过https方式访问。 43 $base_url = isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off' ? 'https' : 'http'; 44 $base_url .= '://'. $_SERVER['HTTP_HOST']; 45 //去掉文件名部分。 46 $base_url .= str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); 47 } 48 49 else 50 { 51 //如果发现没有$_SERVER['HTTP_HOST'],则直接设置为localhost 52 $base_url = 'http://localhost/'; 53 } 54 55 //保存到base_url中,以后像辅助函数uri_helper就可以通过base_url()调用出Config组件此值。 56 $this->set_item('base_url', $base_url); 57 } 58 } 59 60 // -------------------------------------------------------------------- 61 62 /** 63 * Load Config File 64 * 先解释一下load方法的参数,$file就是配置文件名。配置文件目录一般为应用目录(application)/config/下 65 * 下面会有很多个针对不同方面配置的文件,而我们通过Config组件加载的配置信息都会保存在Config::$config这个 66 * 属性里面,所以第二个参数$use_sections就是设置是否当前配置文件是否以独立一个数组的形式充当Config::$config 67 * 的一个元素加入,如果为true,则$config是一个两层的数组,如果为false,则单纯将配置文件里面的配置信息合并。 68 * 例如配置文件abc.php,如果为true,则会以$config['abc']['xxx']的形式保存,否则直接合并即会有 69 * $config['xxx']。 70 * 第三个参数只是设置要不要报错而已,如果为true,则只会返回false,如果为false则直接在函数执行时报错。 71 */ 72 function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE) 73 { 74 //接下来这一行代码是为了方便我们调用的时候既可以以xxx.php的形式传参,也可以只以xxx(无后缀)的形式。 75 //另外如果$file为空,则默认是加载config.php 76 $file = ($file == '') ? 'config' : str_replace('.php', '', $file); 77 78 $found = FALSE; 79 $loaded = FALSE; 80 81 //这个$this->_config_paths默认只有应用目录application/ 82 foreach ($this->_config_paths as $path) 83 { 84 //分别从某特定环境的配置目录和默认的配置目录里面寻找。 85 $check_locations = defined('ENVIRONMENT') 86 ? array(ENVIRONMENT.'/'.$file, $file) 87 : array($file); 88 89 foreach ($check_locations as $location) 90 { 91 $file_path = $path.'config/'.$location.'.php'; 92 93 if (in_array($file_path, $this->is_loaded, TRUE)) 94 { 95 $loaded = TRUE; 96 continue 2;//如果是已经加载过了,那么在Config::$config里面理应当有,所以直接跳出最外层循环。 97 } 98 99 if (file_exists($file_path)) 100 { 101 $found = TRUE;//如果找到了一个,就不再找了。所以相同的配置文件仅会有一个有效。 102 break; 103 } 104 } 105 106 //$found是用于判断在此$path里面,遍历上面的$check_locations有没有找到 107 //而$load则是用于判断两层遍历以后,最终有没有把配置文件加载进来。 108 if ($found === FALSE) 109 { 110 continue; 111 } 112 113 //配置文件就是在这个地方加载的, 114 include($file_path); 115 116 //下面这句可以看出,我们在包含的配置文件里面必须要有名为$config的数组。 117 //如果配置信息格式不合法,看情况($$fail_gracefully的作用)处理错误。 118 if ( ! isset($config) OR ! is_array($config)) 119 { 120 121 if ($fail_gracefully === TRUE) 122 { 123 return FALSE; 124 } 125 show_error('Your '.$file_path.' file does not appear to contain a valid configuration array.'); 126 } 127 128 //下面就是$use_sections的作用,根据它来规定当前加载的配置信息的保存形式。 129 if ($use_sections === TRUE) 130 { 131 if (isset($this->config[$file])) 132 { 133 $this->config[$file] = array_merge($this->config[$file], $config); 134 } 135 else 136 { 137 $this->config[$file] = $config; 138 } 139 } 140 else 141 { 142 $this->config = array_merge($this->config, $config); 143 } 144 145 //保存哪些文件已经加载过,下次再调用此load方法的时候,通过它来避免重复加载,减少不必要的操作。 146 $this->is_loaded[] = $file_path; 147 unset($config); 148 149 $loaded = TRUE; 150 log_message('debug', 'Config file loaded: '.$file_path); 151 break; 152 } 153 154 //加载失败,按情况处理错误。 155 if ($loaded === FALSE) 156 { 157 if ($fail_gracefully === TRUE) 158 { 159 return FALSE; 160 } 161 show_error('The configuration file '.$file.'.php'.' does not exist.'); 162 } 163 164 //来到这里,说明了一切都很顺利,返回true。 165 return TRUE; 166 } 167 168 // -------------------------------------------------------------------- 169 170 /** 171 * Fetch a config file item 172 * 取得某一配置项的内容,如果知道上面Config::load($file, $use_sections, $fail_gracefully);方法 173 * 中$use_sections的意义的话,那个下面的$index意义就很容易理解了。 174 */ 175 function item($item, $index = '') 176 { 177 if ($index == '') 178 { 179 if ( ! isset($this->config[$item])) 180 { 181 return FALSE; 182 } 183 184 $pref = $this->config[$item]; 185 } 186 else 187 { 188 if ( ! isset($this->config[$index])) 189 { 190 return FALSE; 191 } 192 193 if ( ! isset($this->config[$index][$item])) 194 { 195 return FALSE; 196 } 197 198 $pref = $this->config[$index][$item]; 199 } 200 201 return $pref; 202 } 203 204 // -------------------------------------------------------------------- 205 206 /** 207 * Fetch a config file item - adds slash after item (if item is not empty) 208 */ 209 //此方法仅仅是对配置信息进行一些修剪处理而已。 210 function slash_item($item) 211 { 212 if ( ! isset($this->config[$item])) 213 { 214 return FALSE; 215 } 216 //如果此配置项仅仅是包含一些对配置无效的字符,则直接返回空。 217 if( trim($this->config[$item]) == '') 218 { 219 return ''; 220 } 221 222 //保证以一条/结尾。 223 return rtrim($this->config[$item], '/').'/'; 224 } 225 226 // -------------------------------------------------------------------- 227 228 /** 229 * Site URL 230 */ 231 //我们经常通过url_helper的site_url获得我们在项目中想要的路径,其实真正执行的是Config::site_url()这个方法。 232 function site_url($uri = '') 233 { 234 //$uri参数实质可以是数组的 235 236 237 if ($uri == '') 238 { 239 return $this->slash_item('base_url').$this->item('index_page'); 240 } 241 242 //根据当前的路由格式返回相应的uri_string 243 if ($this->item('enable_query_strings') == FALSE) 244 { 245 $suffix = ($this->item('url_suffix') == FALSE) ? '' : $this->item('url_suffix'); 246 return $this->slash_item('base_url').$this->slash_item('index_page').$this->_uri_string($uri).$suffix; 247 } 248 else 249 { 250 return $this->slash_item('base_url').$this->item('index_page').'?'.$this->_uri_string($uri); 251 } 252 } 253 254 // ------------------------------------------------------------- 255 256 /** 257 * Base URL 258 */ 259 function base_url($uri = '') 260 { 261 return $this->slash_item('base_url').ltrim($this->_uri_string($uri),'/'); 262 } 263 264 // ------------------------------------------------------------- 265 266 /** 267 * Build URI string for use in Config::site_url() and Config::base_url() 268 */ 269 protected function _uri_string($uri) 270 { 271 /** 272 * 按当前规定路由格式,返回正确的uri_string. 273 * 主要是如果当参数$uri是数组的时候的一些处理。 274 */ 275 if ($this->item('enable_query_strings') == FALSE) 276 { 277 if (is_array($uri)) 278 { 279 $uri = implode('/', $uri); 280 } 281 $uri = trim($uri, '/'); 282 } 283 else 284 { 285 if (is_array($uri)) 286 { 287 $i = 0; 288 $str = ''; 289 foreach ($uri as $key => $val) 290 { 291 $prefix = ($i == 0) ? '' : '&'; 292 $str .= $prefix.$key.'='.$val; 293 $i++; 294 } 295 $uri = $str; 296 } 297 } 298 return $uri; 299 } 300 301 // -------------------------------------------------------------------- 302 303 /** 304 * System URL 305 */ 306 function system_url() 307 { 308 //厄,下面这行这么奇葩的代码,其实只是为拿到系统目录的路径而已。 309 //正则部分是首先去掉BASEPATH中多余重复的“/”,然后再拆分为数组。最后通过end()函数来拿到系统目录名。 310 $x = explode("/", preg_replace("|/*(.+?)/*$|", "\1", BASEPATH)); 311 return $this->slash_item('base_url').end($x).'/'; 312 } 313 314 // -------------------------------------------------------------------- 315 316 /** 317 * Set a config file item 318 */ 319 function set_item($item, $value) 320 { 321 $this->config[$item] = $value; 322 } 323 324 // -------------------------------------------------------------------- 325 326 /** 327 * Assign to Config 328 */ 329 /** 330 * 下面这个方法在CodeIgniter.php中调用过,是为把在index.php里设置的配置信息交给Config组件。 331 * 实质也是通过上面的Config::set_item();方法设置。 332 */ 333 function _assign_to_config($items = array()) 334 { 335 if (is_array($items)) 336 { 337 foreach ($items as $key => $val) 338 { 339 $this->set_item($key, $val); 340 } 341 } 342 } 343 }