程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 網頁編程 >> PHP編程 >> 關於PHP編程 >> CI框架源碼閱讀---------URI.php

CI框架源碼閱讀---------URI.php

編輯:關於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)       {           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 pattern               // 大概意思是 由於php5.3.0  字符 - 被增加為需要轉義的。 所以這裡在使用str_replace()要添加preg_quote()來對-進行轉義               if ( ! 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的我們自定義的後綴。       * @access  private       * @return  void       */       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拆分正段同時對每個段進行過濾,並存入$this->segments[]中       * @access  private       * @return  void       */       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開始保存。這樣做可以更簡單的使用使用因為段數組和真實的段有個1:1的關系        * This function re-indexes the $this->segment array so that it        * starts at 1 rather than 0.  Doing so makes it simpler to        * use functions like $this->uri->segment(n) since there is         * a 1:1 relationship 關系 between the segment array and the actual 真實的 segments.        *        * @access  private        * @return  void        */       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       * 獲取一個uri段       * This function returns the URI segment based on the number provided.提供       * 這個函數返回一個基於提供的數字uri段       * @access  public       * @param   integer       * @param   bool       * @return  string       */       function segment($n, $no_result = FALSE)       {           return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];       }          // --------------------------------------------------------------------          /**       * Fetch a URI "routed" Segment       * 返回確定路由後的某一段       * This function returns the re-routed URI segment (assuming 假設 routing rules 規則 are used)       * based on the number provided.  If there is no routing this function returns the       * same result as $this->segment()       * 這個函數返回一個已經路由的基於提供的數字的uri段(假設路由規則已經使用的)       * 如果還沒與路由這個函數將和$this->segment()是一樣的       *       * @access  public       * @param   integer       * @param   bool       * @return  string       */       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       * 根據uri字符串產生一個鍵值對的數組       *       * This function generates and associative 關聯的 array of URI data starting       * at the supplied 由。。。提供 segment. For example, if this is your URI:       *        *  example.com/user/search/name/joe/location/UK/gender/male       *       * You can use this function to generate an array with this prototype:       *       * array (       *          name => joe       *          location => UK       *          gender => male       *       )       * 這個函數由uri段產生一個關聯數組       * 例子:如果你的uri是這樣的       * example.com/user/search/name/joe/location/UK/gender/male       * 那麼將產生一個這樣的原型       * array (       *          name => joe       *          location => UK       *          gender => male       *       )       * @access  public       * @param   integer the starting segment number       * @param   array   an array of default values       * @return  array       */       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       * 跟上一個函數是完全相同的只是它沖洗路由了段數組 (注意看第三個參數)       * @access  public       * @param   integer the starting segment number       * @param   array   an array of default values       * @return  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       * 根據uri字符串或者重新路由的uri字符串產生一個鍵值對數組       * @access  private       * @param   integer the starting segment number 起始段號       * @param   array   an array of default values       * @param   string  which array we should use       * @return  array       */       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';           }           // $n 是不是一個數字           if ( ! is_numeric($n))           {               return $default;           }                      // 緩存uri段列表中是夠存在$n這個key           if (isset($this->keyval[$n]))           {               return $this->keyval[$n];           }              // 總段數小於$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       * 根據一個關聯數組產生一個uri字符串       *       * @access  public       * @param   array   an associative array of key/values       * @return  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       * 獲取一個uri段並且添加一個/       *       * @access  public       * @param   integer       * @param   string       * @return  string       */       function slash_segment($n, $where = 'trailing')       {           return $this->_slash_segment($n, $where, 'segment');       }          // --------------------------------------------------------------------          /**       * Fetch a URI Segment and add a trailing slash       * 獲取一個已經路由的uri段並且添加/       * @access  public       * @param   integer       * @param   string       * @return  string       */       function slash_rsegment($n, $where = 'trailing')       {           return $this->_slash_segment($n, $where, 'rsegment');       }          // --------------------------------------------------------------------          /**       * Fetch a URI Segment and add a trailing slash - helper function       *       * @access  private       * @param   integer       * @param   string       * @param   string       * @return  string       */       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       * 獲取段數組       * @access  public       * @return  array       */       function segment_array()       {           return $this->segments;       }          // --------------------------------------------------------------------          /**       * Routed Segment Array       * 獲取已經路由的段數組       * @access  public       * @return  array       */       function rsegment_array()       {           return $this->rsegments;       }          // --------------------------------------------------------------------          /**       * Total number of segments       * 獲取段總數       * @access  public       * @return  integer       */       function total_segments()       {           return count($this->segments);       }          // --------------------------------------------------------------------          /**       * Total number of routed segments       * 獲取已經路由的段的總數       * @access  public       * @return  integer       */       function total_rsegments()       {           return count($this->rsegments);       }          // --------------------------------------------------------------------          /**       * Fetch the entire URI string       *       * @access  public       * @return  string       */       function uri_string()       {           return $this->uri_string;       }             // --------------------------------------------------------------------          /**       * Fetch the entire Re-routed URI string       *  www.2cto.com      * @access  public       * @return  string       */       function ruri_string()       {           return '/'.implode('/', $this->rsegment_array());       }      }   // END URI Class      /* End of file URI.php */   /* Location: ./system/core/URI.php */    

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved