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 }