日期:2014-05-17  浏览次数:20468 次

CI框架源码阅读---------URI.php
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP 5.1.6 or newer
 *
 * @package		CodeIgniter
 * @author		ExpressionEngine Dev Team
 * @copyright	Copyright (c) 2008 - 2011, EllisLab, Inc.
 * @license		http://codeigniter.com/user_guide/license.html
 * @link		http://codeigniter.com
 * @since		Version 1.0
 * @filesource
 */

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

/**
 * URI Class
 *
 * Parses 解析 URIs and determines routing
 *
 * @package		CodeIgniter
 * @subpackage	Libraries
 * @category	URI
 * @author		ExpressionEngine Dev Team
 * @link		http://codeigniter.com/user_guide/libraries/uri.html
 */
class CI_URI {

	/**
	 * List of cached uri segments
	 * 缓存uri段列表
	 * @var array
	 * @access public
	 */
	var	$keyval			= array();
	/**
	 * Current uri string
	 * 当前uri字符串
	 * @var string
	 * @access public
	 */
	var $uri_string;
	/**
	 * List of uri segments
	 * uri段列表
	 * @var array
	 * @access public
	 */
	var $segments		= array();
	/**
	 * Re-indexed list of uri segments
	 * Starts at 1 instead of 0
	 * 从1开始重新索引rui段列表
	 * @var array
	 * @access public
	 */
	var $rsegments		= array();

	/**
	 * Constructor
	 *
	 * Simply globalizes the $RTR object.  The front
	 * loads the Router class early on so it's not available
	 * normally as other classes are.
	 *
	 * @access	public
	 */
	function __construct()
	{
		$this->config =& load_class('Config', 'core');
		log_message('debug', "URI Class Initialized");
	}


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

	/**
	 * Get the URI String
	 *
	 * @access	private
	 * @return	string
	 */
	function _fetch_uri_string()
	{
		// 下面的uri_protocol是在config.php里面的一个配置项,
		// 其实是问你用哪种方式去检测uri的信息的意思,
  		// 默认是AUTO,自动检测,也就是通过各种方式检测,直至检测到,或者全部方式都检测完。。
		if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')
		{
			// Is the request coming from the command line?
			// 开始尝试各种方式,主要有:命令行,REQUEST_URI, PATH_INFO, QUERY_STRING. 
   
   			// 下面会多次出现$this->_set_uri_string($str)这个方法,这个方法没别的,就是把$str经过
   			// 过滤和修剪后值给$this->uri_string属性,在这里暂时可以理解为就是赋值。 
   
   			// 如果脚本是在命令行模式下运行的话,那么参数就是通过$_SERVER['argv']来传递。下面的
   			// $this->_parse_cli_args();就是拿到符合我们需要的路由相关的一些参数
			// 如果你没用命令行执行脚本的话,下面这个if暂时可以不用管。
			// 这时候我们发现URI类用函数php_sapi_name()来测试不同的环境
			// 在apache环境下面输出的结果是“apache2handler”; 
			// 在cgi模式下输出的结果是“cgi-fcgi” 
			// 要是在命令行模式下面运行的话,那么输出的结果是:”cli” 

			if (php_sapi_name() == 'cli' or defined('STDIN'))
			{
				$this->_set_uri_string($this->_parse_cli_args());
				return;
			}

			// Let's try the REQUEST_URI first, this will work in most situations
			// 查找uri
			if ($uri = $this->_detect_uri())
			{
				// 如果找到uri 设置$this->uri_string
				$this->_set_uri_string($uri);
				return;
			}

			// Is there a PATH_INFO variable? 
			// Note: some servers seem 似乎 to have trouble 麻烦 with getenv() so we'll test it two ways
			// 获取path $_SERVER['PATH_INFO'] 并不是每次请求都会有的所以当没有的时候使用getenv('PATH_INFO')
			$path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
			if (trim($path, '/') != '' && $path != "/".SELF)
			{
				$this->_set_uri_string($path);
				return;
			}

			// No PATH_INFO?... What about QUERY_STRING?
			// 如果没有找到$_SERVER['PATH_INFO'] 我们使用QUERY_STRING
			$path =  (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
			if (trim($path, '/') != '')
			{
				$this->_set_uri_string($path);
				return;
			}

			// As a last ditch effort lets try using the $_GET array
			// 如果PATH_INFO和QUERY_STRING都没找到我们只能使用$_GET
			if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
			{
				$this->_set_uri_string(key($_GET));
				return;
			}

			// We've exhausted all our options...
			// 经过以上的努力我们还没有找到uri那么我们就真的找不到了
			$this->uri_string = '';
			return;
		}

		// 这里重新写了一遍获取uri_protocol 其实我觉得