八)CodeIgniter源码分析之Config.php

  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 }
原文地址:https://www.cnblogs.com/qxbj/p/4415222.html