首頁 後端開發 php教程 CI框架源码翻阅-Router.php

CI框架源码翻阅-Router.php

Jun 13, 2016 am 11:16 AM
controller gt this

CI框架源码阅读---------Router.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 */// ------------------------------------/** * Router Class * * Parses URIs and determines routing * * @package		CodeIgniter * @subpackage	Libraries * @author		ExpressionEngine Dev Team * @category	Libraries * @link		http://codeigniter.com/user_guide/general/routing.html */class CI_Router {	/**	 * Config class	 * 配置	 * @var object	 * @access public	 */	var $config;	/**	 * List of routes	 * 路由列表,值来自APPPATH/config/route.php	 * @var array	 * @access public	 */	var $routes			= array();	/**	 * List of error routes	 * 错误路由列表	 * @var array	 * @access public	 */	var $error_routes	= array();	/**	 * Current class name	 * URI中的Controller	 * @var string	 * @access public	 */	var $class			= '';	/**	 * Current method name	 * URI中显示调用的函数,默认为index()	 * @var string	 * @access public	 */	var $method			= 'index';	/**	 * Sub-directory that contains the requested controller class	 * URI中现实的目录信息	 * @var string	 * @access public	 */	var $directory		= '';	/**	 * Default controller (and method if specific 确定的)	 * 默认控制器	 * @var string	 * @access public	 */	var $default_controller;	/**	 * Constructor	 *	 * Runs the route mapping function.	 * 加载并实例化config类和URI类	 */	function __construct()	{		$this->config =& load_class('Config', 'core');		$this->uri =& load_class('URI', 'core');		log_message('debug', "Router Class Initialized");	}	// --------------------------------	/**	 * Set the route mapping	 *	 * This function determines 确定,决心 what should be served based on the URI request,	 * as well as any "routes" that have been set in the routing config file.	 * 设置默认的路由信息,如果不存在控制器信息,则根据routes.php的设置来加载默认的控制器,	 *	 * @access	private	 * @return	void	 */	function _set_routing()	{		// Are query strings enabled in the config file?  Normally CI doesn't utilize 运用 query strings		// since URI segments are more search-engine friendly, but they can optionally 视情况 be used.		// If this feature is enabled, we will gather  the directory/class/method a little differently		// 如果项目是允许通过query_strings的形式,并且有通过$_GET的方式请求控制器的话,则以query_string形式路由		// 上面这里为什么还要判断有没有通过get的方式指定控制器?		// 其实是因为如果允许query_string的形式请求路由,但是却没有在APPPATH/config/config.php下配置 		// controller_trigger,function_trigger,directory_trigger这三项的话,也是不能使用query_strings形式的		// 此时,我们依然会采用“段”的形式。				$segments = array();		if ($this->config->item('enable_query_strings') === TRUE AND isset($_GET[$this->config->item('controller_trigger')]))		{			//取得目录名,控制名和方法名传递的变量名。这三项都是在config/config.php里面定义的。			if (isset($_GET[$this->config->item('directory_trigger')]))			{				$this->set_directory(trim($this->uri->_filter_uri($_GET[$this->config->item('directory_trigger')])));				$segments[] = $this->fetch_directory();			}			if (isset($_GET[$this->config->item('controller_trigger')]))			{				$this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));				$segments[] = $this->fetch_class();			}			if (isset($_GET[$this->config->item('function_trigger')]))			{				$this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')])));				$segments[] = $this->fetch_method();			}		}		// Load the routes.php file.		// 根据当前环境加载APPPATH下面的routes.php		if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))		{			include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');		}		elseif (is_file(APPPATH.'config/routes.php'))		{			include(APPPATH.'config/routes.php');		}		// 下面的这个$route变量是在routes.php中定义的用来设置默认的控制器和默认的404页面		$this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;		unset($route);// 利用完就干掉,过河拆桥,毫不留情。		// Set the default controller so we can display it in the event事件		// the URI doesn't correlated 相关的 to a valid 有效的 controller.		// 根据刚才的配置信息,设定默认控制器,没有的话,就为FLASE。		$this->default_controller = ( ! isset($this->routes['default_controller']) OR $this->routes['default_controller'] == '') ? FALSE : strtolower($this->routes['default_controller']);		// Were there any query string segments?  If so, we'll validate them and bail out since we're done.		// 验证有没有通过query string的方式拿到目录名,控制名和方法名其中的任何一个。		// 如果拿到了就直接确定路由返回		if (count($segments) > 0)		{			// 确定并设置路由。			return $this->_validate_request($segments);		}		// Fetch the complete URI string		// 这个函数的作用是从uri中检测处理,把我们确定路由需要的信息(例如index.php/index/welcome/1后		// 面index/welcome/1这串)放到$this->uri->uri_string中。		$this->uri->_fetch_uri_string();		// Is there a URI string? If not, the default controller specified in the "routes" file will be shown.		// 如果uri_string为空的话,那么就用把路由设置为默认的。		/*if ($this->uri->uri_string == '')		{			return $this->_set_default_controller();		}*/		// Do we need to remove the URL suffix?		// 去掉URI后缀,因为CI允许在uri后面加后缀,但它其实对我们寻找路由是多余,而且会造成影响的,所以先去掉。		$this->uri->_remove_url_suffix();		// Compile 编译 the segments into an array		// 将uri拆分正段同时对每个段进行过滤,并存入$this->segments[]中		$this->uri->_explode_segments();		// Parse any custom routing that may exist		// 处理路由,根据路由设置APPPATH/config/routes.php来		$this->_parse_routes();		// Re-index the segment array so that it starts with 1 rather than 0		// 将uri段索引设置为从1开始		$this->uri->_reindex_segments();	}	// --------------------------------	/**	 * Set the default controller	 * 设置默认的控制器	 * @access	private	 * @return	void	 */	function _set_default_controller()	{		// 在Router::_set_routing()函数中从配置文件里面读取默认控制器名,如果没有就有FALSE		// 本文件的158行		if ($this->default_controller === FALSE)		{			show_error("Unable to determine what should be displayed. A default route has not been specified in the routing file.");		}		// Is the method being specified?		// 通过判断$this->default_controller有没有/来确定是否有指定的方法		// 如果没有设置为默认方法index		if (strpos($this->default_controller, '/') !== FALSE)		{			$x = explode('/', $this->default_controller);			$this->set_class($x[0]);			$this->set_method($x[1]);			$this->_set_request($x);		}		else		{			$this->set_class($this->default_controller);			$this->set_method('index');			$this->_set_request(array($this->default_controller, 'index'));		}		// re-index the routed segments array so it starts with 1 rather than 0		// 重新索引段,使得出来的段以下标1开始保存。 		$this->uri->_reindex_segments();		log_message('debug', "No URI present. Default controller set.");	}	// --------------------------------	/**	 * Set the Route	 * 设置路由	 * This function takes 取走,预备动作 an array of URI segments as	 * input, and sets the current class/method	 *	 * @access	private	 * @param	array	 * @param	bool	 * @return	void	 */	function _set_request($segments = array())	{		// Router::_validate_request()的作用是检测寻找出一个正确存在的路由,并确定它		$segments = $this->_validate_request($segments);		//  这个函数是由_set_default_controller总调用的看216-230行会发现这个$segments 是肯定不会为空的		//  那么下面这两句可能是为了防止本方法在其他的地方调用当参数为空的时候调用_set_default_controller()		//  再调用回来$segments就不会为空了,因为当$segments为空的时候是不可能进行设置路由的。		if (count($segments) == 0)		{			return $this->_set_default_controller();		}				// 设置类名也就是目录名		$this->set_class($segments[0]);		// 如果方法名存在则设置如果不存在则设置为index		if (isset($segments[1]))		{			// A standard method request			$this->set_method($segments[1]);		}		else		{			// This lets the "routed" segment array identify that the default			// index method is being used.			$segments[1] = 'index';		}		// Update our "routed" segment array to contain the segments.		// Note: If there is no custom routing, this array will be		// identical to $this->uri->segments		// 更新路由的段数组,这里如果没有自定义的路由那么将和$this->uri->segments是一样的		$this->uri->rsegments = $segments;	}	// --------------------------------	/**	 * Validates 使有效 the supplied segments.  Attempts 企图 to determine 决定 the path to	 * the controller.	 * 使提供的段有效并企图决定控制器的路径	 * @access	private	 * @param	array	 * @return	array	 */	function _validate_request($segments)	{		// ??????????????		if (count($segments) == 0)		{			return $segments;		}		// Does the requested controller exist in the root folder?		// 确定存在$segments[0]是否存在于APPPATH/controllers/文件夹下的php文件		if (file_exists(APPPATH.'controllers/'.$segments[0].'.php'))		{			return $segments;		}		// Is the controller in a sub-folder?		// $segments[0]是否为APPPATH/controllers下的子目录		if (is_dir(APPPATH.'controllers/'.$segments[0]))		{			// Set the directory and remove it from the segment array			// 如果的确是目录,那么就可以确定路由的目录部分了。 设置目录			$this->set_directory($segments[0]);			// 去掉目录部分。进一步进行路由寻找。			$segments = array_slice($segments, 1);						// 如果uri请求中除了目录还有其它段,那说明是有请求某指定控制器的。			if (count($segments) > 0)			{				// Does the requested controller exist in the sub-folder?				// 判断请求的$segments[0]是不是在于APPPATH/controllers/的子目录中php文件				if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php'))				{					// 报错也有两方式,一种是默认的,一种是自义定的。					// 下面这个404_override就是在config/routes.php定义的一个路由找不					// 到时候的默认处理控制器了,如果有定义我们调用它。					if ( ! empty($this->routes['404_override']))					{												$x = explode('/', $this->routes['404_override']);						// 把刚才设置好的路由的目录部分去掉,因为现在路由是我们定义的404路由。						$this->set_directory('');						// 这里可以看出,我们定义的404路由是不允许放在某个目录下的,只能直接放在controllers/下						$this->set_class($x[0]);						$this->set_method(isset($x[1]) ? $x[1] : 'index');						return $x;					}					else					{						// 默认404报错						show_404($this->fetch_directory().$segments[0]);					}				}			}			else			{				// 如果uri请求中只有目录我们才会来到这				// Is the method being specified 指定的 in the route?				// 下面这个判断只是判断一下$this->default_controller有没有指定方法而已。				if (strpos($this->default_controller, '/') !== FALSE)				{					$x = explode('/', $this->default_controller);					$this->set_class($x[0]);					$this->set_method($x[1]);				}				else				{					$this->set_class($this->default_controller);					$this->set_method('index');				}				// Does the default controller exist in the sub-folder?				// 判断APPPATH/controllers/目录/下面是否存在默认的方法				if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$this->default_controller.'.php'))				{					$this->directory = '';					return array();				}			}			return $segments;		}		// If we've gotten 达到 this far 遥远的 it means that the URI does not correlate 使相关联 to a valid		// controller class.  We will now see if there is an override		// 来到这里,就说明了,即找不到controllers/下相应的控制器,也找不到这样的目录。那就报错咯。		if ( ! empty($this->routes['404_override']))		{			$x = explode('/', $this->routes['404_override']);			$this->set_class($x[0]);			$this->set_method(isset($x[1]) ? $x[1] : 'index');			return $x;		}		// Nothing else to do at this point but show a 404		// 展示一个404页面		show_404($segments[0]);	}	// --------------------------------	/**	 *  Parse Routes	 *  解析路由	 * This function matches 匹配 any routes that may exist in	 * the config/routes.php file against 针对,反对 the URI to	 * determine 决定,决心 if the class/method need to be remapped.重新绘制地图	 *	 * @access	private	 * @return	void	 */	function _parse_routes()	{		// Turn the segment array into a URI string		// 将segments数组转为uri字符串的形式		$uri = implode('/', $this->uri->segments);		// Is there a literal 文字的,字面的 match?  If so we're done		// 如果这个uri是routes.php中定义的那么。。。。。		if (isset($this->routes[$uri]))		{			return $this->_set_request(explode('/', $this->routes[$uri]));		}		// Loop through the route array looking for wild-cards		foreach ($this->routes as $key => $val)		{			// Convert wild-cards to RegEx 使用通配符进行正则转换			// 如果$key 中含有:any 转换为.+  , :num 转换为 [0-9]+			$key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));			// Does the RegEx match? 进行正则匹配			// 从这里可以看出如果routes.php 中的$route的key是可以使用:any 或者 :num			// 来进行匹配的。举个例子来说			// routes.php 中有 $route['show:any:num'] = 'anynum'; 			// 这样的两个配置那么我们就可以将showaa123这样的uri匹配到了它对应的值就是anynum			if (preg_match('#^'.$key.'$#', $uri))			{								// Do we have a back-reference?如果$val中有$并且$key中有(				// 这个if的作用我没看懂。。。待高人解救				// [email protected]				if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)				{					// 将uri中能匹配到得字符替换成$val					$val = preg_replace('#^'.$key.'$#', $val, $uri);				}				return $this->_set_request(explode('/', $val));			}		}		// If we got this far it means we didn't encounter a		// matching route so we'll set the site default route		// 如果我们走到这一步,这意味着我们没有遇到一个匹配的路由		// 所以我们将设置网站默认路由		$this->_set_request($this->uri->segments);	}	// --------------------------------	/**	 * Set the class name	 *	 * @access	public	 * @param	string	 * @return	void	 */	function set_class($class)	{		$this->class = str_replace(array('/', '.'), '', $class);	}	// --------------------------------	/**	 * Fetch the current class	 *	 * @access	public	 * @return	string	 */	function fetch_class()	{		return $this->class;	}	// --------------------------------	/**	 *  Set the method name	 *	 * @access	public	 * @param	string	 * @return	void	 */	function set_method($method)	{		$this->method = $method;	}	// --------------------------------	/**	 *  Fetch the current method	 *	 * @access	public	 * @return	string	 */	function fetch_method()	{		if ($this->method == $this->fetch_class())		{			return 'index';		}		return $this->method;	}	// --------------------------------	/**	 *  Set the directory name	 *	 * @access	public	 * @param	string	 * @return	void	 */	function set_directory($dir)	{		$this->directory = str_replace(array('/', '.'), '', $dir).'/';	}	// --------------------------------	/**	 *  Fetch the sub-directory (if any) that contains the requested controller class	 *	 * @access	public	 * @return	string	 */	function fetch_directory()	{		return $this->directory;	}	// --------------------------------	/**	 * Set the controller overrides	 * 控制器覆盖	 * 这个函数可以讲目录,控制器,方法重新覆盖一遍。	 * @access	public	 * @param	array	 * @return	null	 */	function _set_overrides($routing)	{		if ( ! is_array($routing))		{			return;		}		if (isset($routing['directory']))		{			$this->set_directory($routing['directory']);		}		if (isset($routing['controller']) AND $routing['controller'] != '')		{			$this->set_class($routing['controller']);		}		if (isset($routing['function']))		{			$routing['function'] = ($routing['function'] == '') ? 'index' : $routing['function'];			$this->set_method($routing['function']);		}	}}// END Router Class/* End of file Router.php *//* Location: ./system/core/Router.php */
登入後複製

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

華為GT3 Pro和GT4的差異是什麼? 華為GT3 Pro和GT4的差異是什麼? Dec 29, 2023 pm 02:27 PM

許多用戶在選擇智慧型手錶的時候都會選擇的華為的品牌,其中華為GT3pro和GT4都是非常熱門的選擇,不少用戶都很好奇華為GT3pro和GT4有什麼區別,下面就給大家介紹一下二者。華為GT3pro和GT4有什麼差別一、外觀GT4:46mm和41mm,材質是玻璃鏡板+不鏽鋼機身+高分纖維後殼。 GT3pro:46.6mm和42.9mm,材質是藍寶石玻璃鏡+鈦金屬機身/陶瓷機身+陶瓷後殼二、健康GT4:採用最新的華為Truseen5.5+演算法,結果會更加的精準。 GT3pro:多了ECG心電圖和血管及安

SpringBoot掃描不到Controller怎麼解決 SpringBoot掃描不到Controller怎麼解決 May 14, 2023 am 08:10 AM

SpringBoot小白創建項目​​,掃描不到Controller一系列問題1.2.3.4.5.6.還有一個方法是在啟動服務類的入門,添加@ComponentScan(basePackages={“xxx.xxx.xx”,“xxx.xxx .xx”})裡面的是包的全限定名,可以為多個SpringBoot自訂controller無法掃描到SpringBoot自訂controller路由找不到,原因是啟動類別和自訂的Controller包不在同一級目錄下。官方建議application.java放的位

修復:截圖工具在 Windows 11 中不起作用 修復:截圖工具在 Windows 11 中不起作用 Aug 24, 2023 am 09:48 AM

為什麼截圖工具在Windows11上不起作用了解問題的根本原因有助於找到正確的解決方案。以下是截圖工具可能無法正常工作的主要原因:對焦助手已開啟:這可以防止截圖工具開啟。應用程式損壞:如果截圖工具在啟動時崩潰,則可能已損壞。過時的圖形驅動程式:不相容的驅動程式可能會幹擾截圖工具。來自其他應用程式的干擾:其他正在運行的應用程式可能與截圖工具衝突。憑證已過期:升級過程中的錯誤可能會導致此issu簡單的解決方案這些適合大多數用戶,不需要任何特殊的技術知識。 1.更新視窗與Microsoft應用程式商店應用程

SpringBoot多controller如何加入URL前綴 SpringBoot多controller如何加入URL前綴 May 12, 2023 pm 06:37 PM

前言在某些情況下,服務的controller中前綴是一致的,例如所有URL的前綴都為/context-path/api/v1,需要為某些URL加上統一的前綴。能想到的處理辦法為修改服務的context-path,在context-path中加上api/v1,這樣修改全域的前綴能夠解決上面的問題,但存在弊端,如果URL存在多個前綴,例如有些URL需要前綴為api/v2,就無法區分了,如果服務中的一些靜態資源不想添加api/v1,也無法區分。下面透過自訂註解的方式實現某些URL前綴的統一添加。一、

如何修復無法連線到iPhone上的App Store錯誤 如何修復無法連線到iPhone上的App Store錯誤 Jul 29, 2023 am 08:22 AM

第1部分:初始故障排除步驟檢查蘋果的系統狀態:在深入研究複雜的解決方案之前,讓我們先從基礎知識開始。問題可能不在於您的設備;蘋果的伺服器可能會關閉。造訪Apple的系統狀態頁面,查看AppStore是否正常運作。如果有問題,您所能做的就是等待Apple修復它。檢查您的網路連接:確保您擁有穩定的網路連接,因為「無法連接到AppStore」問題有時可歸因於連接不良。嘗試在Wi-Fi和行動數據之間切換或重置網路設定(「常規」>「重置」>「重置網路設定」>設定)。更新您的iOS版本:

php提交表单通过后,弹出的对话框怎样在当前页弹出,该如何解决 php提交表单通过后,弹出的对话框怎样在当前页弹出,该如何解决 Jun 13, 2016 am 10:23 AM

php提交表单通过后,弹出的对话框怎样在当前页弹出php提交表单通过后,弹出的对话框怎样在当前页弹出而不是在空白页弹出?想实现这样的效果:而不是空白页弹出:------解决方案--------------------如果你的验证用PHP在后端,那么就用Ajax;仅供参考:HTML code

聊聊Vue2為什麼能透過this存取各種選項中屬性 聊聊Vue2為什麼能透過this存取各種選項中屬性 Dec 08, 2022 pm 08:22 PM

這篇文章帶大家解讀vue原始碼,來介紹一下Vue2中為什麼可以使用 this 存取各種選項中的屬性,希望對大家有幫助!

一篇搞懂this指向,追趕70%的前端人 一篇搞懂this指向,追趕70%的前端人 Sep 06, 2022 pm 05:03 PM

同事因為this指向的問題卡住的bug,vue2的this指向問題,使用了箭頭函數,導致拿不到對應的props。當我跟他介紹的時候他竟然不知道,隨後也刻意的看了一下前端交流群,至今最起碼還有70%以上的前端程式設計師搞不明白,今天給大家分享一下this指向,如果啥都沒學會,請給我一個大嘴巴子。

See all articles