URI.php–URI类提供了帮助你分割URI字符串的函数集合。如果你使用URI路由功能,那么你就可以通过分段来重新分发地址栏信息。
1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
2. class CI_URI {
3.
4. //缓存的URI分段数组
5. var $keyval = array();
6.
7. //当前URI字符串
8. var $uri_string;
9.
10. //URI分段数组
11. var $segments = array();
12.
13. //重新排列的URI数组
14. var $rsegments = array();
15.
16. function __construct()
17. {
18. $this->config =& load_class('Config', 'core');
19. log_message('debug', "URI Class Initialized");
20. }
21.
22.
23. //获取URI字符串
24. function _fetch_uri_string()
25. {
26. if (strtoupper($this->config->item('uri_protocol')) == 'AUTO')
27. {
28. // Is the request coming from the command line?
29. if (php_sapi_name() == 'cli' or defined('STDIN'))
30. {
31. $this->_set_uri_string($this->_parse_cli_args());
32. return;
33. }
34.
35. // Let's try the REQUEST_URI first, this will work in most situations
36. if ($uri = $this->_detect_uri())
37. {
38. $this->_set_uri_string($uri);
39. return;
40. }
41.
42. // Is there a PATH_INFO variable?
43. // Note: some servers seem to have trouble with getenv() so we'll test it two ways
44. $path = (isset($_SERVER['PATH_INFO'])) ? $_SERVER['PATH_INFO'] : @getenv('PATH_INFO');
45. if (trim($path, '/') != '' && $path != "/".SELF)
46. {
47. $this->_set_uri_string($path);
48. return;
49. }
50.
51. // No PATH_INFO?... What about QUERY_STRING?
52. $path = (isset($_SERVER['QUERY_STRING'])) ? $_SERVER['QUERY_STRING'] : @getenv('QUERY_STRING');
53. if (trim($path, '/') != '')
54. {
55. $this->_set_uri_string($path);
56. return;
57. }
58.
59. // As a last ditch effort lets try using the $_GET array
60. if (is_array($_GET) && count($_GET) == 1 && trim(key($_GET), '/') != '')
61. {
62. $this->_set_uri_string(key($_GET));
63. return;
64. }
65.
66. // We've exhausted all our options...
67. $this->uri_string = '';
68. return;
69. }
70.
71. $uri = strtoupper($this->config->item('uri_protocol'));
72.
73. if ($uri == 'REQUEST_URI')
74. {
75. $this->_set_uri_string($this->_detect_uri());
76. return;
77. }
78. elseif ($uri == 'CLI')
79. {
80. $this->_set_uri_string($this->_parse_cli_args());
81. return;
82. }
83.
84. $path = (isset($_SERVER[$uri])) ? $_SERVER[$uri] : @getenv($uri);
85. $this->_set_uri_string($path);
86. }
87.
88. //设置URI字符串
89. function _set_uri_string($str)
90. {
91. // Filter out control characters
92. $str = remove_invisible_characters($str, FALSE);
93.
94. // If the URI contains only a slash we'll kill it
95. $this->uri_string = ($str == '/') ? '' : $str;
96. }
97.
98. //检测URI字符串
99. private function _detect_uri()
100. {
101. if ( ! isset($_SERVER['REQUEST_URI']) OR ! isset($_SERVER['SCRIPT_NAME']))
102. {
103. return '';
104. }
105.
106. $uri = $_SERVER['REQUEST_URI'];
107. if (strpos($uri, $_SERVER['SCRIPT_NAME']) === 0)
108. {
109. $uri = substr($uri, strlen($_SERVER['SCRIPT_NAME']));
110. }
111. elseif (strpos($uri, dirname($_SERVER['SCRIPT_NAME'])) === 0)
112. {
113. $uri = substr($uri, strlen(dirname($_SERVER['SCRIPT_NAME'])));
114. }
115.
116. // This section ensures that even on servers that require the URI to be in the query string (Nginx) a correct
117. // URI is found, and also fixes the QUERY_STRING server var and $_GET array.
118. if (strncmp($uri, '?/', 2) === 0)
119. {
120. $uri = substr($uri, 2);
121. }
122. $parts = preg_split('#\?#i', $uri, 2);
123. $uri = $parts[0];
124. if (isset($parts[1]))
125. {
126. $_SERVER['QUERY_STRING'] = $parts[1];
127. parse_str($_SERVER['QUERY_STRING'], $_GET);
128. }
129. else
130. {
131. $_SERVER['QUERY_STRING'] = '';
132. $_GET = array();
133. }
134.
135. if ($uri == '/' || empty($uri))
136. {
137. return '/';
138. }
139.
140. $uri = parse_url($uri, PHP_URL_PATH);
141.
142. // Do some final cleaning of the URI and return it
143. return str_replace(array('//', '../'), '/', trim($uri, '/'));
144. }
145.
146. //解析命令行参数
147. private function _parse_cli_args()
148. {
149. $args = array_slice($_SERVER['argv'], 1);
150.
151. return $args ? '/' . implode('/', $args) : '';
152. }
153.
154. //过滤URI字符串
155. function _filter_uri($str)
156. {
157. if ($str != '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') == FALSE)
158. {
159. // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
160. // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
161. if ( ! preg_match("|^[".str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-'))."]+$|i", $str))
162. {
163. show_error('The URI you submitted has disallowed characters.', 400);
164. }
165. }
166.
167. // Convert programatic characters to entities
168. $bad = array('$', '(', ')', '%28', '%29');
169. $good = array('$', '(', ')', '(', ')');
170.
171. return str_replace($bad, $good, $str);
172. }
173.
174. //删除URI后缀
175. function _remove_url_suffix()
176. {
177. if ($this->config->item('url_suffix') != "")
178. {
179. $this->uri_string = preg_replace("|".preg_quote($this->config->item('url_suffix'))."$|", "", $this->uri_string);
180. }
181. }
182.
183. //拆分URI字符串
184. function _explode_segments()
185. {
186. foreach (explode("/", preg_replace("|/*(.+?)/*$|", "\\1", $this->uri_string)) as $val)
187. {
188. // Filter segments for security
189. $val = trim($this->_filter_uri($val));
190.
191. if ($val != '')
192. {
193. $this->segments[] = $val;
194. }
195. }
196. }
197.
198. //重新排序URI分段数组
199. function _reindex_segments()
200. {
201. array_unshift($this->segments, NULL);
202. array_unshift($this->rsegments, NULL);
203. unset($this->segments[0]);
204. unset($this->rsegments[0]);
205. }
206.
207. //从URI分段数组中取一部分
208. function segment($n, $no_result = FALSE)
209. {
210. return ( ! isset($this->segments[$n])) ? $no_result : $this->segments[$n];
211. }
212.
213. //从路由解析后的URI分段数组中取一部分
214. function rsegment($n, $no_result = FALSE)
215. {
216. return ( ! isset($this->rsegments[$n])) ? $no_result : $this->rsegments[$n];
217. }
218.
219. //从URI字符串或者路由解析后的字符串生成一个关联数组
220. function uri_to_assoc($n = 3, $default = array())
221. {
222. return $this->_uri_to_assoc($n, $default, 'segment');
223. }
224. //从路由解析后的字符串生成一个关联数组
225. function ruri_to_assoc($n = 3, $default = array())
226. {
227. return $this->_uri_to_assoc($n, $default, 'rsegment');
228. }
229.
230. //从URI字符串或者路由解析后的字符串生成一个关联数组
231. function _uri_to_assoc($n = 3, $default = array(), $which = 'segment')
232. {
233. if ($which == 'segment')
234. {
235. $total_segments = 'total_segments';
236. $segment_array = 'segment_array';
237. }
238. else
239. {
240. $total_segments = 'total_rsegments';
241. $segment_array = 'rsegment_array';
242. }
243.
244. if ( ! is_numeric($n))
245. {
246. return $default;
247. }
248.
249. if (isset($this->keyval[$n]))
250. {
251. return $this->keyval[$n];
252. }
253.
254. if ($this->$total_segments() < $n)
255. {
256. if (count($default) == 0)
257. {
258. return array();
259. }
260.
261. $retval = array();
262. foreach ($default as $val)
263. {
264. $retval[$val] = FALSE;
265. }
266. return $retval;
267. }
268.
269. $segments = array_slice($this->$segment_array(), ($n - 1));
270.
271. $i = 0;
272. $lastval = '';
273. $retval = array();
274. foreach ($segments as $seg)
275. {
276. if ($i % 2)
277. {
278. $retval[$lastval] = $seg;
279. }
280. else
281. {
282. $retval[$seg] = FALSE;
283. $lastval = $seg;
284. }
285.
286. $i++;
287. }
288.
289. if (count($default) > 0)
290. {
291. foreach ($default as $val)
292. {
293. if ( ! array_key_exists($val, $retval))
294. {
295. $retval[$val] = FALSE;
296. }
297. }
298. }
299.
300. // Cache the array for reuse
301. $this->keyval[$n] = $retval;
302. return $retval;
303. }
304.
305. //从关联数组生成一个URI字符串
306. function assoc_to_uri($array)
307. {
308. $temp = array();
309. foreach ((array)$array as $key => $val)
310. {
311. $temp[] = $key;
312. $temp[] = $val;
313. }
314.
315. return implode('/', $temp);
316. }
317.
318. //获取路由解析后的URI分段数组中的某个元素
319. function slash_segment($n, $where = 'trailing')
320. {
321. return $this->_slash_segment($n, $where, 'segment');
322. }
323.
324. //获取路由解析后的URI分段数组中的某个元素,并在其后添加正斜线
325. function slash_rsegment($n, $where = 'trailing')
326. {
327. return $this->_slash_segment($n, $where, 'rsegment');
328. }
329.
330. //取得URI中的某一段并添加正斜线
331. function _slash_segment($n, $where = 'trailing', $which = 'segment')
332. {
333. $leading = '/';
334. $trailing = '/';
335.
336. if ($where == 'trailing')
337. {
338. $leading = '';
339. }
340. elseif ($where == 'leading')
341. {
342. $trailing = '';
343. }
344.
345. return $leading.$this->$which($n).$trailing;
346. }
347.
348. //URI分段数组
349. function segment_array()
350. {
351. return $this->segments;
352. }
353.
354. //路由解析后的URI分段数组
355. function rsegment_array()
356. {
357. return $this->rsegments;
358. }
359.
360. //URI分段数组长度
361. function total_segments()
362. {
363. return count($this->segments);
364. }
365.
366. //路由解析后的URI分段数组长度
367. function total_rsegments()
368. {
369. return count($this->rsegments);
370. }
371.
372. //获取整个URI字符串
373. function uri_string()
374. {
375. return $this->uri_string;
376. }
377.
378.
379. //获取整个路由后的URI字符串
380. function ruri_string()
381. {
382. return '/'.implode('/', $this->rsegment_array());
383. }
384.
385. }