Home  >  Article  >  Backend Development  >  CI framework source code reading---------Router.php_PHP tutorial

CI framework source code reading---------Router.php_PHP tutorial

WBOY
WBOYOriginal
2016-07-14 10:09:16882browse

[php]  

/** 
 * 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
* Route list, value comes from APPPATH/config/route.php
* @var array
* @access public
*/  
    var $routes         = array();  
    /**
* List of error routes
* Error routing list
* @var array
* @access public
*/  
    var $error_routes   = array();  
    /** 
     * Current class name 
     * URI中的Controller 
     * @var string 
     * @access public 
     */  
    var $class          = '';  
    /**
* Current method name
* The function called is displayed in the URI, the default is index()
* @var string
* @access public
*/  
    var $method         = 'index';  
    /**
* Sub-directory that contains the requested controller class
* The actual directory information in the URI
* @var string
* @access public
*/  
    var $directory      = '';  
    /**
* Default controller (and method if specific)
* Default controller
* @var string
* @access public
*/  
    var $default_controller;  
  
    /**
* Constructor
*
* Runs the route mapping function.
* Load and instantiate the config class and URI class
*/  
    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.
* Set the default routing information. If there is no controller information, load the default controller according to the settings of 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
// If the project allows the query_strings format and requests the controller via $_GET, it will be routed in the query_string format
// Why do we need to judge whether the controller is specified by get method above?
// Actually it’s because if query_string request routing is allowed, but it is not configured under APPPATH/config/config.php
// Controller_trigger, function_trigger, directory_trigger cannot be used in query_strings form
// At this time, we will still use the "segment" form.
$segments = array();
if ($this->config->item('enable_query_strings') === TRUE AND isset($_GET[$this->config->item('controller_trigger')]))
{
                                        //Get the variable names passed by the directory name, control name and method name. These three items are defined in 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.
// Load routes.php under APPPATH according to the current environment
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');
} }
// The following $route variable is defined in routes.php to set the default controller and default 404 page
$this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
Unset ($ Route); // Drain it after use, dismantle the bridge across the river, and no mercy.
// Set the default controller so we can display it in the event
// the URI doesn't correlated to a valid controller.
// Set the default controller based on the configuration information just now. If not, it will be 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.
// Verify whether any of the directory name, control name and method name is obtained through query string.
// If you get it, directly determine the route and return
if (count($segments) > 0)
{
// Determine and set the route.
Return $ this- & gt; _Validate_request ($ segments);
} }
// Fetch the complete URI string
// The purpose of this function is to detect and process the uri and get the information we need to determine the routing (such as index.php/index/welcome/1)
// Put the string index/welcome/1) into $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.
// If uri_string is empty, then set the route to the default.
/*if ($this->uri->uri_string == '')
{
return $this->_set_default_controller();
}*/
// Do we need to remove the URL suffix?
// Remove the URI suffix, because CI allows adding a suffix after the uri, but it is actually redundant for us to find routes and will have an impact, so remove it first.
$this->uri->_remove_url_suffix();
// Compile compile the segments into an array
// Split the uri into regular segments, filter each segment, and store it in $this->segments[]
$this->uri->_explode_segments();
// Parse any custom routing that may exist
// Process routing, set APPPATH/config/routes.php according to routing
$this->_parse_routes();
// Re-index the segment array so that it starts with 1 rather than 0
// Set the uri segment index to start from 1
$this->uri->_reindex_segments();
}
//------------------------------------------------ -----------------------
/**
* Set the default controller
* Set default controller
* @access private
* @return void
*/
function _set_default_controller()
{
// Read the default controller name from the configuration file in the Router::_set_routing() function, if not there will be FALSE
// Line 158 of this file
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?
// Determine whether there is a specified method by judging whether $this->default_controller has /.
// If not set as the default method 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
                                     // Re-index the segment so that the outgoing segments are saved starting with the subscript 1.
$this->uri->_reindex_segments();
log_message('debug', "No URI present. Default controller set.");
}
//------------------------------------------------ -----------------------
/**
* Set the Route
* Set routing
* This function takes take, prepare action 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())
{
// The function of Router::_validate_request() is to detect and find a correctly existing route and determine it
$segments = $this->_validate_request($segments);
// This function is called by _set_default_controller. If you look at lines 216-230, you will find that $segments will definitely not be empty.
// Then the following two sentences may be to prevent this method from being called in other places and calling _set_default_controller() when the parameter is empty
// If you call it back, $segments will not be empty, because it is impossible to set routing when $segments is empty.
if (count($segments) == 0)
{
Return $ this- & gt; _set_default_Controller ();
} }
// Set the class name which is also the directory name
$this->set_class($segments[0]);
// If the method name exists, set it. If it does not exist, set it to index
if (isset($segments[1]))
{
// A standard request method
$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
// Update the segment array of the route. If there is no custom route here, it will be the same as $this->uri->segments
$this->uri->rsegments = $segments;
}
//------------------------------------------------ -----------------------
/**
* Validates validates the supplied segments. Attempts attempt to determine the path to
* the controller.
* Validates the provided segment and 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?
// Determine whether $segments[0] exists in the php file under the APPPATH/controllers/ folder
if (file_exists(APPPATH.'controllers/'.$segments[0].'.php'))
{
return $segments;
} }
// Is the controller in a sub-folder?
// Whether $segments[0] is a subdirectory under APPPATH/controllers
if (is_dir(APPPATH.'controllers/'.$segments[0]))
{
// Set the directory and remove it from the segment array
                                                                                                    // If it is indeed a directory, then the directory part of the route can be determined. Set directory
$this->set_directory($segments[0]);
                      // Remove the directory part. Further route search.
$segments = array_slice($segments, 1);
                                                                     
// If there are other paragraphs in addition to the directory in the URI request, it means that there is a specified controller.
if (count($segments) > 0)
                                                                 
                                                                                                                                                                                                 
// Determine the request's $ segments [0] whether the app file in the Appppath/Controller/subdirectory
                    if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php'))
                                                                         
// There are two ways to report an error, one is default, and the other is self -determined.
                                                                                                                                                                                                                        // The following 404_override is a route defined in config/routes.php that cannot be found
// The default processing controller at that time, if we are defined, we call it.
                  if ( ! emptyempty($this->routes['404_override']))  
                                                                                 
                                                         
                                                                                                                                                                                                                        $x = explode('/', $this->routes['404_override']);
// Remove the directory part of the route that I just set, because the route is now the 404 route we defined.
$this->set_directory('');
// It can be seen here that the 404 routing we define is not allowed to be placed in a certain directory, and we can only be placed directly in controllers/below
                                                                                                                                                                 
                                                                                        $this->set_method(isset($x[1]) ? $x[1] : 'index');
                        return $x;                                          
                                                                       
              else  
                                                                                 
                                                                                                                                                                                                                                                                                                 
show_404($this->fetch_directory().$segments[0]);
                                                                       
        }  
      }  
        else  
                                                                 
// If we only have a directory in the URI request, we will come to this
                       // Is the method being specified in the route?
// The judgment below is just judging the $ this-& gt; default_controller. Is there any specified method?
              if (strpos($this->default_controller, '/') !== FALSE)
                                                                         
                                                                                                                                                                             
$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 ( ! emptyempty($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
* Parse route
* This function matches any routes that may exist in
* the config/routes.php file against, against the URI to
* determine decision, determination if the class/method need to be remapped. Redraw the map
*
* @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-& gt; _Set_request (explode ('/', $ this-& gt; routes [$ uri]));
} }
// Loop through the route array looking for wild-cards
foreach ($this->routes as $key => $val)
{
// Convert Wild-CARDS To Regex Using the pass to make a regular conversion
// If the $ key contains: Any convert to.+,: Num convert to [0-9]+
$key = str_replace(':any', '.+', str_replace(':num', '[0-9]+', $key));
// Does the RegEx match? Perform regular matching
                                                                                                                                                                                                                        
                                                // To match. For example
                                                                                                                                                                                                    $route['show:any:num'] = 'anynum';                                      
// With these two configurations, we can match a uri like showaa123 to its corresponding value which is anynum
if (preg_match('#^'.$key.'$#', $uri))
                                                                 
                                                       
                                                                                                                                                                                                                                                             // Do we have a back-reference? If there is $ in $val and there is (
in $key
                                     // I don’t understand the function of this if. . . Waiting for rescue by experts
                                                                                                                                                                                                                                                                            to
                if (strpos($val, '$') !== FALSE AND strpos($key, '(') !== FALSE)
                                                                         
// Replace the characters in the URI to the $ value
$val = preg_replace('#^'.$key.'$#', $val, $uri);
        }  
Return $ this- & gt; _Set_request (explode ('/', $ value));
      }  
} }
// If we got this far it means we didn't encounter a
// matching route so we'll set the site default route
// If we get this far, it means we didn’t encounter a matching route
// So we will set the website 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
* Controller overrides
* This function can cover directories, controllers, and methods again.
* @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'] != '')  
        {  www.2cto.com
            $this->set_class($routing['controller']);  
        }  
  
        if (isset($routing['function']))  
        {  www.2cto.com
            $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 */  

www.bkjia.comtruehttp://www.bkjia.com/PHPjc/477681.htmlTechArticle[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 * * @packag...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn