찾다
백엔드 개발PHP 튜토리얼CI框架源码翻阅-Router.php

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으로 문의하세요.
PHP는 사용자 세션을 어떻게 식별합니까?PHP는 사용자 세션을 어떻게 식별합니까?May 01, 2025 am 12:23 AM

phpidifiesauser의 sssessionusessessioncookiesandssessionids.1) whensession_start () iscalled, phpgeneratesauniquessessionStoredInacookienamedPhpsSessIdonSeuser 'sbrowser.2) thisidallowsphptoretrievessessionDataTromServer.

PHP 세션을 확보하기위한 모범 사례는 무엇입니까?PHP 세션을 확보하기위한 모범 사례는 무엇입니까?May 01, 2025 am 12:22 AM

PHP 세션의 보안은 다음 측정을 통해 달성 할 수 있습니다. 1. Session_REGENEREAT_ID ()를 사용하여 사용자가 로그인하거나 중요한 작업 일 때 세션 ID를 재생합니다. 2. HTTPS 프로토콜을 통해 전송 세션 ID를 암호화합니다. 3. 세션 _save_path ()를 사용하여 세션 데이터를 저장하고 권한을 올바르게 설정할 보안 디렉토리를 지정하십시오.

PHP 세션 파일은 기본적으로 어디에 저장됩니까?PHP 세션 파일은 기본적으로 어디에 저장됩니까?May 01, 2025 am 12:15 AM

phpsessionfilesarestoredInTheRectorySpecifiedBysession.save_path, 일반적으로/tmponunix-likesystemsorc : \ windows \ temponwindows.tocustomizethis : 1) austession_save_path () toSetacustomDirectory, verlyTeCustory-swritation;

PHP 세션에서 데이터를 어떻게 검색합니까?PHP 세션에서 데이터를 어떻게 검색합니까?May 01, 2025 am 12:11 AM

toretrievedatafromAphPsession, startSessionstart_start () andaccessvariblesinthe $ _sessionArray.forexample : 1) startthessession : session_start (). 2) retrievedata : $ _ session [ 'username']; echo "Welcome,". $ username;

세션을 사용하여 쇼핑 카트를 구현할 수있는 방법은 무엇입니까?세션을 사용하여 쇼핑 카트를 구현할 수있는 방법은 무엇입니까?May 01, 2025 am 12:10 AM

세션을 사용하여 효율적인 쇼핑 카트 시스템을 구축하는 단계에는 다음이 포함됩니다. 1) 세션의 정의와 기능을 이해합니다. 세션은 요청에 따라 사용자 상태를 유지하는 데 사용되는 서버 측 스토리지 메커니즘입니다. 2) 쇼핑 카트에 제품 추가와 같은 기본 세션 관리를 구현합니다. 3) 제품 수량 관리 및 삭제 지원 고급 사용으로 확장; 4) 세션 데이터를 지속하고 보안 세션 식별자를 사용하여 성능 및 보안을 최적화합니다.

PHP에서 인터페이스를 어떻게 생성하고 사용합니까?PHP에서 인터페이스를 어떻게 생성하고 사용합니까?Apr 30, 2025 pm 03:40 PM

이 기사는 PHP의 인터페이스를 생성, 구현 및 사용하는 방법을 설명하여 코드 구성 및 유지 관리에 대한 이점에 중점을 둡니다.

crypt ()와 password_hash ()의 차이점은 무엇입니까?crypt ()와 password_hash ()의 차이점은 무엇입니까?Apr 30, 2025 pm 03:39 PM

이 기사에서는 PHP의 암호 해싱에 대한 Crypt ()와 Password_hash ()의 차이점에 대해 논의하여 최신 웹 애플리케이션에 대한 구현, 보안 및 적합성에 중점을 둡니다.

PHP의 크로스 사이트 스크립팅 (XSS)을 어떻게 방지 할 수 있습니까?PHP의 크로스 사이트 스크립팅 (XSS)을 어떻게 방지 할 수 있습니까?Apr 30, 2025 pm 03:38 PM

기사는 입력 유효성 검사, 출력 인코딩 및 OWASP ESAPI 및 HTML 청정기와 같은 도구를 통해 PHP의 크로스 사이트 스크립팅 (XSS) 방지에 대해 논의합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

안전한 시험 브라우저

안전한 시험 브라우저

안전한 시험 브라우저는 온라인 시험을 안전하게 치르기 위한 보안 브라우저 환경입니다. 이 소프트웨어는 모든 컴퓨터를 안전한 워크스테이션으로 바꿔줍니다. 이는 모든 유틸리티에 대한 액세스를 제어하고 학생들이 승인되지 않은 리소스를 사용하는 것을 방지합니다.

SublimeText3 Linux 새 버전

SublimeText3 Linux 새 버전

SublimeText3 Linux 최신 버전

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

PhpStorm 맥 버전

PhpStorm 맥 버전

최신(2018.2.1) 전문 PHP 통합 개발 도구