codeigniter源代码分析之URI处理类 URI.php
2014-04-27 21:51
537 查看
对http请求的uri进行解析处理
Router中uri请求为get的时候是不会调用到这里
这里处理的是默认请求跟path_info形式的请求
代码注释如下
总结:
_fetch_uri_string 获取uri string
_detect_uri 通过REQUEST_URI处理 uri的参数部分
_explode_segments 切割uri中(path_info)参数部分
下面很多对segments的操作
Code Tips:
1、方法 _uri_to_assoc 还有点没弄懂
Router中uri请求为get的时候是不会调用到这里
这里处理的是默认请求跟path_info形式的请求
代码注释如下
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class CI_URI { var $keyval = array(); var $uri_string; var $segments = array(); var $rsegments = array(); function __construct() { $this->config =& load_class('Config', 'core'); log_message('debug', "URI Class Initialized"); } function _fetch_uri_string() { if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')//自动识别 { if (php_sapi_name() == 'cli' or defined('STDIN'))//命令行 { $this->_set_uri_string($this->_parse_cli_args()); return; } if ($uri = $this->_detect_uri())//detect_uri 获取 { $this->_set_uri_string($uri);// 设置uri_string return; } // 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 $path = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING'); if (trim($path, '/') != '') { $this->_set_uri_string($path); return; } // url?arg1 if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '') { $this->_set_uri_string(key($_GET)); return; } // 设置为空 $this->uri_string = ''; return; } $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; } $path = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri); $this->_set_uri_string($path); } function _set_uri_string($str) { // 这里意味着 如果uri参数部分为空 或者为GET请求 不过一般情况GET请求是过不来的 // Router先处理GET 成功就return了 // it means 参数部分为空就会返回 空的 uri_string 这样在Router中会调用set_default_controller $str = remove_invisible_characters($str, FALSE);//过滤看不见的字符 不过滤URL $this->uri_string = ($str == '/') ? '' : $str; //if (uri_string == '/') uri_string = ''; } private function _detect_uri() { if ( ! isset($_SERVER['REQUEST_URI']) OR ! isset($_SERVER['SCRIPT_NAME'])) {//REQUEST_URI SCRIPT_NAME 不存在很可能是命令行 ? return ''; } // 获取URL的参数部分 赋值给 uri 变量 $uri = $_SERVER['REQUEST_URI']; 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']))); } if (strncmp($uri, '?/', 2) === 0) {//如果uri是以 ?/ 开始的 说明这个请求可能是 Nginx 去除url中的'?/' $uri = substr($uri, 2); } $parts = preg_split('#\?#i', $uri, 2);//用?将uri切割成两部分 $uri = $parts[0]; // GET请求的 parts[0] 为空 参数列在 parts[1] // PATH_INFO 请求 parts[0] 就是参数列 /var1/var2... if (isset($parts[1])) { $_SERVER['QUERY_STRING'] = $parts[1]; parse_str($_SERVER['QUERY_STRING'], $_GET); } else { $_SERVER['QUERY_STRING'] = ''; $_GET = array(); } if ($uri == '/' || empty($uri)) { // GET请求 和默认请求都将执行这里 return '/'; } $uri = parse_url($uri, PHP_URL_PATH); return str_replace(array('//', '../'), '/', trim($uri, '/')); } // 解析CLI模式的参数 private function _parse_cli_args() { $args = array_slice($_SERVER['argv'], 1); return $args ? '/' . implode('/', $args) : ''; } function _filter_uri($str) { // permitted_uri_chars 可以指定uri中允许出现的字符 if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE) { 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); } } $bad = array('$', '(', ')', '%28', '%29'); $good = array('$', '(', ')', '(', ')'); // 用good(对应字符的HTML形式的十进制编码)替换uri中出现的bad 字符 return str_replace($bad, $good, $str); } function _remove_url_suffix() { // 去除uri后缀 if ($this->config->item('url_suffix') != "") { $this->uri_string = preg_replace("|".preg_quote($this->config->item('url_suffix'))."$|", "", $this->uri_string); } } function _explode_segments() { foreach (explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val) {//PATH_INFO模式生成segments $val = trim($this->_filter_uri($val)); if ($val != '') { // 为URI的segments赋值 $this->segments[] = $val; } } } // 将数组的0index unset 数组从1开始索引 function _reindex_segments() { array_unshift($this->segments, NULL); array_unshift($this->rsegments, NULL); unset($this->segments[0]); unset($this->rsegments[0]); } // 返回指定的uri段 function segment($n, $no_result = FALSE) { return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n]; } function rsegment($n, $no_result = FALSE) { return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n]; } function uri_to_assoc($n = 3, $default = array()) { return $this->_uri_to_assoc($n, $default, 'segment'); } function ruri_to_assoc($n = 3, $default = array()) { return $this->_uri_to_assoc($n, $default, 'rsegment'); } 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];//keyval中存在就返回索取的值 } if ($this->$total_segments() < $n)//总segments数小于请求的索引 { if (count($default) == 0) { return array(); } $retval = array(); foreach ($default as $val) { $retval[$val] = FALSE;//用default array 设置 } return $retval; } $segments = array_slice($this->$segment_array(), ($n - 1));//取出n后面的数据 $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; } // 将segments数组拼接成 uri字符串 function assoc_to_uri($array) { $temp = array(); foreach ((array)$array as $key => $val) { $temp[] = $key; $temp[] = $val; } return implode('/', $temp); } function slash_segment($n, $where = 'trailing') { return $this->_slash_segment($n, $where, 'segment'); } function slash_rsegment($n, $where = 'trailing') { return $this->_slash_segment($n, $where, 'rsegment'); } function _slash_segment($n, $where = 'trailing', $which = 'segment') { $leading = '/'; $trailing = '/'; if ($where == 'trailing') { $leading = ''; } elseif ($where == 'leading') { $trailing = ''; } return $leading.$this->$which($n).$trailing; } function segment_array() { return $this->segments; } function rsegment_array() { return $this->rsegments; } function total_segments() { return count($this->segments); } function total_rsegments() { return count($this->rsegments); } function uri_string() { return $this->uri_string; } function ruri_string() { return '/'.implode('/', $this->rsegment_array()); } }
总结:
_fetch_uri_string 获取uri string
_detect_uri 通过REQUEST_URI处理 uri的参数部分
_explode_segments 切割uri中(path_info)参数部分
下面很多对segments的操作
Code Tips:
1、方法 _uri_to_assoc 还有点没弄懂
相关文章推荐
- codeigniter源代码分析 - 错误处理类 Exception.php
- codeigniter源代码分析之配置类Config.php
- CodeIgniter 图像处理类 源代码分析
- CodeIgniter源码分析之URI.php
- codeigniter源代码分析之输出类 Output.php
- codeigniter源代码分析之系统全局函数 Common.php
- PHP源代码数组统计count分析
- CodeIgniter源码阅读(三)(URI.php)
- Discuz!源代码分析系列(4)-./include/template.func.php(模板)
- Apache源代码全景分析第二卷——HTTP请求处理
- fleaphp框架源代码分析
- CodeIgniter配置之routes.php用法实例分析
- php框架codeigniter框架源代码分析,注释中文化,类库分析(一)
- CodeIgniter配置之autoload.php自动加载用法分析
- CodeIgniter框架源码笔记(6)——支持友好的URI地址:路由类Router.php
- piglatin.php源代码分析
- PHP中PDO的事务处理分析
- Android 开源框架Universal-Image-Loader完全解析(八)---从源代码分析Android-Universal-Image-Loader的缓存处理机制
- PHP源代码分析:Zend HashTable详解
- PHP的正则处理函数总结分析