CI框架源码阅读---------URI.php

作者:襄阳西继迅达电梯有限公司  发布时间:2017-09-09 10:20:05
CI框架源码阅读---------URI.php [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 其实我觉得完全可以只获取一次嘛。。。

$uri = strtoupper($this->config->item('uri_protocol'));

// 下面就是根据不同的方式来选择不同的办法获取uri了

if ($uri == 'REQUEST_URI')

{

$this->_set_uri_string($this->_detect_uri());

return;

}

elseif ($uri == 'CLI')

{

$this->_set_uri_string($this->_parse_cli_args());

return;

}

// 如果你定义的uri_protocol是在AUTO REQUEST_URI CLI这三种方式之外的就执行下面这段了。

$path = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);

$this->_set_uri_string($path);

}

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

/**

* Set the URI String

*

* @access public

* @param string

* @return string

*/

function _set_uri_string($str)

{

// Filter out control characters

// 过滤字符串 remove_invisible_characters 函数式在common.php中

$str = remove_invisible_characters($str, FALSE);

// If the URI contains only a slash we'll kill it

// 如果字符串只包含一个/则清空

$this->uri_string = ($str == '/') ? '' : $str;

}

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

/**

* Detects the URI

* 查找uri

* This function will detect the URI automatically and fix the query string

* if necessary. 必需品

* 如果有必要的话,这个函数将自动查找uri并且固定查询字符串。

*

* @access private

* @return string

*/

private function _detect_uri()

{

// 如果两个值有一个没有则返回(两个变量是从web server那边来的,碰到一些特别的server程序, 这个是有可能为空的.)

if ( ! isset($_SERVER['REQUEST_URI']) OR ! isset($_SERVER['SCRIPT_NAME']))

{

return '';

}

// 获取uri

$uri = $_SERVER['REQUEST_URI'];

// 如果SCRIPT_NAME 在$uri 中第一次出现的位置是0

if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)

{

// 去掉uri 和 SCRIPT_NAME 相同的部分

$uri = substr($uri, strlen($_SERVER['SCRIPT_NAME']));

}

// 这里作用同上 只是将$_SERVER['SCRIPT_NAME']换成了

// dirname($_SERVER['SCRIPT_NAME'])

elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)

{

$uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));

}

// This section ensures 保证 that even on servers that require the URI

// to be in the query string (Nginx) a correct 正确的

// URI is found, and also fixes 修理 the QUERY_STRING server var and $_GET array.

// 这部分保证,uri可以被正确的找到即使是在Nginx服务器上,并且还修复了的QUERY_STRING服务器和$ _GET数组。

// 判断$uri的前两个字符是不是?/

if (strncmp($uri, '?/', 2) === 0)

{

// 去掉前两个字符

$uri = substr($uri, 2);

}

// 用正册对字符串进行分割

$parts = preg_split('#\?#i', $uri, 2);

$uri = $parts[0];

// 如果是能通过上述的正则分割出两段,那么,是通过query_string即?的形式进行路由访问

if (isset($parts[1]))

{

$_SERVER['QUERY_STRING'] = $parts[1];

// 函数把查询字符串解析到$_GET变量中。

parse_str($_SERVER['QUERY_STRING'], $_GET);

}

else

{

$_SERVER['QUERY_STRING'] = '';

$_GET = array();

}

// 如果为/,或者为空,有两种情况,要么就是通过query_string即?的形式进行路由访问,

// 所以此时$parts[0]就是等于下面两种可能,同时我们

// 已经通过$parts[1]拿到要拿的信息,专题系统,则可以返回。

// 要么就是以段的形式,但是段的信息为空,即直接访问入口文件而没有

// 任何路由信息的传递,也可以直接返回。

if ($uri == '/' || emptyempty($uri))

{

return '/';

}

//返回这个url的path部分。

$uri = parse_url($uri, PHP_URL_PATH);

// Do some final cleaning of the URI and return it

// 将uri中的// ../替换成 / 返回

return str_replace(array('//', '../'), '/', trim($uri, '/'));

}

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

/**

* Parse cli arguments

* 解析cli参数

* Take each command line argument and assume it is a URI segment.

* 如果你在命令行中这么操作

* php d:/wamp/www/CodeIgniter/index.php welcome index

* _parse_cli_args() 返回一个 /welcome/index的字符串

*

* @access private

* @return string

*/

private function _parse_cli_args()

{

// 返回在命令行模式下运行时传递的参数。

// 因为第一个参数是当前文件名,所以从第二个开始才是我们要获取的。

$args = array_slice($_SERVER['argv'], 1);

//返回一个由'/'字符串拼接的字符串,因为$this->uri_string是一个字符串。

return $args ? '/' . implode('/', $args) : '';

}

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

/**

* Filter segments 段 for malicious 恶意 characters

* 过滤不合法字符

* @access private

* @param string

* @return string

*/

function _filter_uri($str)

{

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:襄阳网站建设公司 https://www.jingchucn.com/zt/xiangyang_wangzhanjianshe/

  • 上一篇:大妈经济学值得营销策划人借鉴的几个关键点
  • 下一篇:最后一页
  •