標籤:http io ar os sp for 檔案 on div
<?php if ( ! defined(‘BASEPATH‘)) exit(‘No direct script access allowed‘);// ------------------------------------------------------------------------/*** URI Class*/class CI_URI {/*** List of cached uri segments*/var $keyval = array();/*** Current uri string*/var $uri_string;/*** List of uri segments*/var $segments = array();/*** Re-indexed list of uri segments*/var $rsegments = array();/*** Constructor*/function __construct(){$this->config =& load_class(‘Config‘, ‘core‘);log_message(‘debug‘, "URI Class Initialized");}// --------------------------------------------------------------------/*** Get the URI String*///URI組件裡面有很多方法,大都是一些輔助作用的方法,而此方法是URI最主線的一個方法。function _fetch_uri_string(){//下面的uri_protocol是在config.php裡面的一個配置項,其實是問你用哪種方式去檢測uri的資訊的意思,//預設是AUTO,自動檢測,也就是通過各種方式檢測,直至檢測到,或者全部方式都檢測完。。if (strtoupper($this->config->item(‘uri_protocol‘)) == ‘AUTO‘){//開始嘗試各種方式,主要有:命令列,REQUEST_URI, PATH_INFO, QUERY_STRING.//下面會多次出現$this->_set_uri_string($str)這個方法,這個方法沒別的,就是把$str經過//過濾和修剪後值給$this->uri_string屬性,在這裡暫時可以理解為就是賦值。//如果指令碼是在命令列模式下啟動並執行話,那麼參數就是通過$_SERVER[‘argv‘]來傳遞。下面的//$this->_parse_cli_args();就是拿到符合我們需要的路由相關的一些參數鳥~如果大部分//情況你沒用命令列執行指令碼的話,下面這個if暫時可以不用管。if (php_sapi_name() == ‘cli‘ or defined(‘STDIN‘)){$this->_set_uri_string($this->_parse_cli_args());return;}//這種REQUEST_URI方式相對複雜一點,因此封裝在$this->_detect_uri();裡面。//其實大多數情況下,利用REQUEST URI和SCRIPT NAME都會得到我們想要的路徑資訊了。if ($uri = $this->_detect_uri()){$this->_set_uri_string($uri);return;}//PATH_INFO方式,個人覺得這種方式最經濟,只是不是每次請求都有$_SERVER[‘PATH_INFO‘]這個變數。$path = (isset($_SERVER[‘PATH_INFO‘])) ? $_SERVER[‘PATH_INFO‘] : @getenv(‘PATH_INFO‘);if (trim($path, ‘/‘) != ‘‘ && $path != "/".SELF){$this->_set_uri_string($path);return;}//如果是用QUERY_STRING的話,路徑格式一般為index.php?/controller/method/xxx/xxx$path = (isset($_SERVER[‘QUERY_STRING‘])) ? $_SERVER[‘QUERY_STRING‘] : @getenv(‘QUERY_STRING‘);if (trim($path, ‘/‘) != ‘‘){$this->_set_uri_string($path);return;}//上面的方法都不行,那真是奇怪了。。所以嘗試最後一種奇葩的方法,就是從$_GET裡面把那個鍵名拿出來。if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), ‘/‘) != ‘‘){$this->_set_uri_string(key($_GET));return;}// We‘ve exhausted all our options...$this->uri_string = ‘‘;return;}//厄,這裡是因為上面那個獲得uri_protocol配置的語句寫在if裡面,然後又沒賦值到某個變數,所以這裡要再寫一次了//可能是因為大多數情況下,我們都是選擇AUTO方式吧。但是,這樣寫又何必呢。。$uri = strtoupper($this->config->item(‘uri_protocol‘));//其實就是按規定的方式去找路徑而已。。if ($uri == ‘REQUEST_URI‘){$this->_set_uri_string($this->_detect_uri());return;}elseif ($uri == ‘CLI‘){$this->_set_uri_string($this->_parse_cli_args());return;}//如果你在設定檔config.php裡面把這個uri_protocol定義成一種上面都沒有的方式,那麼就會執行下面的代碼。//意思是,就看$_SERVER有沒有這個uri_protocol的變數了,有就給,沒有就拉倒。$path = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);$this->_set_uri_string($path);}// --------------------------------------------------------------------/*** Set the URI String*/function _set_uri_string($str){// Filter out control characters$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*/private function _detect_uri(){//如果這兩個值缺少其中一個,那麼這種方法行不通。if ( ! isset($_SERVER[‘REQUEST_URI‘]) OR ! isset($_SERVER[‘SCRIPT_NAME‘])){return ‘‘;}$uri = $_SERVER[‘REQUEST_URI‘];//取得request_uri//注意下面這個是===0不是false! 接下來這個if 和下面的elseif分別是script_name有檔案名稱和沒有檔案名稱(如//http://abc.com/CI/或者http://abc.com/CI/?c=index&m=welcome等)的不同情況的處理。if (strpos($uri, $_SERVER[‘SCRIPT_NAME‘]) === 0){//去掉共同部分,取得對路由有用的部分。$uri = substr($uri, strlen($_SERVER[‘SCRIPT_NAME‘]));}elseif (strpos($uri, dirname($_SERVER[‘SCRIPT_NAME‘])) === 0){//作用同上$uri = substr($uri, strlen(dirname($_SERVER[‘SCRIPT_NAME‘])));}//這裡是為相容?/abc/xx/的形式。if (strncmp($uri, ‘?/‘, 2) === 0){$uri = substr($uri, 2);}//在這裡$uri可能是?xxx=xx的形式,也可能是直接xxx=xx,也可能是/$parts = preg_split(‘#\?#i‘, $uri, 2);$uri = $parts[0];//如果是能通過上述的正則分割出兩段,那麼,是通過query_string即?的形式進行路由訪問if (isset($parts[1])){$_SERVER[‘QUERY_STRING‘] = $parts[1];parse_str($_SERVER[‘QUERY_STRING‘], $_GET);}else{$_SERVER[‘QUERY_STRING‘] = ‘‘;$_GET = array();}//如果為/,或者為空白,有兩種情況,要麼就是通過query_string,所以此時$parts[0]就是等於下面兩種可能,同時我們//已經通過$parts[1]拿到要拿的資訊,則可以返回。要麼就是以段的形式,但是段的資訊為空白,即直接存取入口檔案而沒有//任何路由資訊的傳遞,也可以直接返回。if ($uri == ‘/‘ || empty($uri)){return ‘/‘;}//這裡我個人覺得是上面的strpos($uri, $_SERVER[‘SCRIPT_NAME‘]) === 0和elseif都無法匹配的時候,//返回這個url的path部分。$uri = parse_url($uri, PHP_URL_PATH);// Do some final cleaning of the URI and return itreturn str_replace(array(‘//‘, ‘../‘), ‘/‘, trim($uri, ‘/‘));}// --------------------------------------------------------------------/*** Parse cli arguments*/private function _parse_cli_args(){//返回在命令列模式下運行時傳遞的參數。$args = array_slice($_SERVER[‘argv‘], 1);//因為第一個參數是當前檔案名稱,所以從第二個開始才是我們要擷取的。//返回一個由‘/‘字串拼接的字串,因為$this->uri_string是一個字串。return $args ? ‘/‘ . implode(‘/‘, $args) : ‘‘;}// --------------------------------------------------------------------/*** Filter segments for malicious characters*///過濾不合法字元function _filter_uri($str){if ($str != ‘‘ && $this->config->item(‘permitted_uri_chars‘) != ‘‘ && $this->config->item(‘enable_query_strings‘) == FALSE){// preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards// compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex patternif ( ! preg_match("|^[".str_replace(array(‘\\-‘, ‘\-‘), ‘-‘, preg_quote($this->config->item(‘permitted_uri_chars‘), ‘-‘))."]+$|i", $str)){show_error(‘The URI you submitted has disallowed characters.‘, 400);}}// Convert programatic characters to entities$bad = array(‘$‘, ‘(‘, ‘)‘, ‘%28‘, ‘%29‘);$good = array(‘$‘, ‘(‘, ‘)‘, ‘(‘, ‘)‘);return str_replace($bad, $good, $str);}// --------------------------------------------------------------------/*** Remove the suffix from the URL if needed*///去掉url的我們自訂的尾碼。function _remove_url_suffix(){if ($this->config->item(‘url_suffix‘) != ""){$this->uri_string = preg_replace("|".preg_quote($this->config->item(‘url_suffix‘))."$|", "", $this->uri_string);}}// --------------------------------------------------------------------/*** Explode the URI Segments. The individual segments will* be stored in the $this->segments array.*///把uri_string拆成段(同時對各段進行過濾),儲存到URI::$segments中。function _explode_segments(){foreach (explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val){// Filter segments for security$val = trim($this->_filter_uri($val));if ($val != ‘‘){$this->segments[] = $val;}}}// --------------------------------------------------------------------/*** Re-index Segments*///使得出來的段以下標1開始儲存。function _reindex_segments(){array_unshift($this->segments, NULL);array_unshift($this->rsegments, NULL);unset($this->segments[0]);unset($this->rsegments[0]);}// --------------------------------------------------------------------/*** Fetch a URI Segment*///返回某一段function segment($n, $no_result = FALSE){return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];}// --------------------------------------------------------------------/*** Fetch a URI "routed" Segment*///返回確定路由後的某一段function rsegment($n, $no_result = FALSE){return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n];}// --------------------------------------------------------------------/*** Generate a key value pair from the URI string*/function uri_to_assoc($n = 3, $default = array()){return $this->_uri_to_assoc($n, $default, ‘segment‘);}/*** Identical to above only it uses the re-routed segment array*/function ruri_to_assoc($n = 3, $default = array()){return $this->_uri_to_assoc($n, $default, ‘rsegment‘);}// --------------------------------------------------------------------/*** Generate a key value pair from the URI string or Re-routed URI string*/function _uri_to_assoc($n = 3, $default = array(), $which = ‘segment‘){if ($which == ‘segment‘){$total_segments = ‘total_segments‘;$segment_array = ‘segment_array‘;}else{$total_segments = ‘total_rsegments‘;$segment_array = ‘rsegment_array‘;}if ( ! is_numeric($n)){return $default;}if (isset($this->keyval[$n])){return $this->keyval[$n];}if ($this->$total_segments() < $n){if (count($default) == 0){return array();}$retval = array();foreach ($default as $val){$retval[$val] = FALSE;}return $retval;}$segments = array_slice($this->$segment_array(), ($n - 1));$i = 0;$lastval = ‘‘;$retval = array();foreach ($segments as $seg){if ($i % 2){$retval[$lastval] = $seg;}else{$retval[$seg] = FALSE;$lastval = $seg;}$i++;}if (count($default) > 0){foreach ($default as $val){if ( ! array_key_exists($val, $retval)){$retval[$val] = FALSE;}}}// Cache the array for reuse$this->keyval[$n] = $retval;return $retval;}// --------------------------------------------------------------------/*** Generate a URI string from an associative array*/function assoc_to_uri($array){$temp = array();foreach ((array)$array as $key => $val){$temp[] = $key;$temp[] = $val;}return implode(‘/‘, $temp);}// --------------------------------------------------------------------/*** Fetch a URI Segment and add a trailing slash*/function slash_segment($n, $where = ‘trailing‘){return $this->_slash_segment($n, $where, ‘segment‘);}// --------------------------------------------------------------------/*** Fetch a URI Segment and add a trailing slash*/function slash_rsegment($n, $where = ‘trailing‘){return $this->_slash_segment($n, $where, ‘rsegment‘);}// --------------------------------------------------------------------/*** Fetch a URI Segment and add a trailing slash - helper function*/function _slash_segment($n, $where = ‘trailing‘, $which = ‘segment‘){$leading = ‘/‘;$trailing = ‘/‘;if ($where == ‘trailing‘){$leading = ‘‘;}elseif ($where == ‘leading‘){$trailing = ‘‘;}return $leading.$this->$which($n).$trailing;}// --------------------------------------------------------------------/*** Segment Array*/function segment_array(){return $this->segments;}// --------------------------------------------------------------------/*** Routed Segment Array*/function rsegment_array(){return $this->rsegments;}// --------------------------------------------------------------------/*** Total number of segments*/function total_segments(){return count($this->segments);}// --------------------------------------------------------------------/*** Total number of routed segments*/function total_rsegments(){return count($this->rsegments);}// --------------------------------------------------------------------/*** Fetch the entire URI string*/function uri_string(){return $this->uri_string;}// --------------------------------------------------------------------/*** Fetch the entire Re-routed URI string*/function ruri_string(){return ‘/‘.implode(‘/‘, $this->rsegment_array());}}
CodeIgniter源碼分析之URI.php