Last active
December 19, 2015 17:19
-
-
Save ball6847/5990464 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |
/* load the MX_Router class */ | |
require APPPATH."third_party/MX/Router.php"; | |
/** | |
* Extends HMVC Modular Extension to modify route parsing | |
* to use Route class instead of default route handler | |
* | |
* | |
**/ | |
class MY_Router extends MX_Router { | |
public function _parse_routes() | |
{ | |
// Turn the segment array into a URI string | |
$uri = '/'.implode('/', $this->uri->segments).'/'; | |
$routes = Route::fetch(); | |
foreach ($routes as $prefix => $group) | |
{ | |
// test prefix match, of not, just skip to next group | |
if (strpos($uri, $prefix) !== 0) | |
{ | |
continue; | |
} | |
// prefix match, try to check full route | |
foreach ($group as $route) | |
{ | |
// Does the RegEx match? | |
if (preg_match('#^'.$route['regex'].'$#', $uri, $params)) | |
{ | |
// matched parameter will be replaced to the result | |
// we don't need [0] so we remove it here | |
unset($params[0]); | |
// prepare default value for route | |
$params = array_merge($route['default'], $params); | |
// replace matched value to the result route | |
foreach ($params as $name => $value) | |
{ | |
$route['handler'] = str_replace(':'.$name, $value, $route['handler']); | |
} | |
// here we go | |
return $this->_set_request(explode('/', $route['handler'])); | |
} | |
} | |
} | |
// 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); | |
} | |
} | |
// ------------------------------------------------------------------------- | |
/** | |
* Main Route class | |
* | |
* @todo more document on this class | |
* | |
**/ | |
class Route { | |
/** | |
* Rules collection | |
**/ | |
public static $rules = array(); | |
/** | |
* Named rules collection | |
**/ | |
public static $named = array(); | |
// ------------------------------------------------------------------------- | |
/** | |
* Create a Route Group Object | |
* | |
* @param String $location route prefix for this group | |
* @return Route_Group | |
**/ | |
public static function group($location) | |
{ | |
return new Route_Group($location); | |
} | |
// ------------------------------------------------------------------------- | |
/** | |
* Create a Route Group object | |
* with admin_base configuration options prepended | |
* this is just to make it quick to add a route to admin area | |
* You can change url to admin anytime by changing $config['admin_base'] in config.php | |
* with named route feature, all your link will be automatically updated | |
* | |
* @param String $location route to admin | |
* @return Route_Group | |
*/ | |
public static function admin($location) | |
{ | |
return self::group('/'.config_item('admin_base').$location); | |
} | |
// ------------------------------------------------------------------------- | |
/** | |
* Fetch Rule collection | |
* | |
* @param String name of group, default to all | |
* @return Array | |
*/ | |
public static function fetch($name = NULL) | |
{ | |
if (is_null($name)) | |
{ | |
return self::$rules; | |
} | |
if (isset(self::$rules[$name])) | |
{ | |
return self::$rules[$name]; | |
} | |
return array(); | |
} | |
// ------------------------------------------------------------------------- | |
/** | |
* Url resolve for a specific route using its name and values | |
* You can then use site_url or redirect to make it a correct link | |
* | |
* @param String $name name of route to resolve | |
* @param Array $params parameter to resolve to route | |
* @return String ready to use route, raise an exception if not found or unable resolve route parameter | |
**/ | |
public static function to($name, $params = array()) | |
{ | |
// try to find pattern in named route | |
if ( ! isset(self::$named[$name])) | |
{ | |
throw new Exception('RouteLinker cannot found any route matched with given name ('.$name.')'); | |
} | |
$pattern = self::$named[$name]['pattern']; | |
// any parameter binding in pattern | |
if (preg_match_all('~:\w+~', $pattern, $matches)) | |
{ | |
// override default value with given parameter | |
$params = array_merge(self::$named[$name]['default'], $params); | |
// replace each token with parameter value | |
// raise an error if unable to resolve value for params | |
foreach ($matches[0] as $args) | |
{ | |
$key = substr($args, 1); | |
// if no value binding for parameter and no default value defined in route | |
// raise an error, cause we cannot let any token left in url | |
if ( ! isset($params[$key]) AND ! isset($default[$key])) | |
{ | |
throw new Exception('RouteLinker cannot found any value for parameter name ('.$key.') in '.self::$named[$name]['pattern']); | |
} | |
$pattern = str_replace($args, $params[$key], $pattern); | |
} | |
} | |
// remove heading and trailing slash from pattern | |
// so this pattern can process with site_url() or redirect() later | |
$pattern = trim($pattern, '/'); | |
return $pattern; | |
} | |
} | |
// ------------------------------------------------------------------------- | |
/** | |
* Route Group class | |
* | |
* Most of time, you wouldn't initiate this class directly | |
* but from returning object of Route::group() or Route::admin() | |
* This class contains 2 important method for your routing | |
* which are Route::group('/')->addRules() and Route::group('/')->addRule() | |
* | |
*/ | |
class Route_Group { | |
protected $base; | |
/** | |
* Constructor, set base route passing by Route::group or Route::admin | |
* | |
* @param String $base base route or route group prefix | |
**/ | |
public function __construct($base = '') | |
{ | |
$this->base = $base; | |
} | |
// ------------------------------------------------------------------------- | |
/** | |
* Add multiple Rules at once | |
* | |
* Generally you should use this method for main route registering | |
* to make your route clean | |
* | |
* @todo write more detail on $rules array structure ... | |
* | |
* @param Array $rules collection of rule definition | |
* | |
**/ | |
public function addRules($rules) | |
{ | |
foreach ($rules as $name => $rule) | |
{ | |
$this->addRule($name, $rule); | |
} | |
} | |
// ------------------------------------------------------------------------- | |
/** | |
* Add single rule, one by one | |
* | |
* @param String $name unique identifier of this route (for internal linking purpose) | |
* @param Array $rule Rule definition | |
**/ | |
public function addRule($name, $rule) | |
{ | |
// create container if not already existed | |
if ( ! isset(Route::$rules[$this->base])) | |
{ | |
Route::$rules[$this->base] = array(); | |
} | |
// prepend prefix to route | |
$rule[0] = $this->base . $rule[0] . '/'; | |
// turn a pattern into regular expression, for using on parsing route in MY_Route::_parse_routes() | |
$regex = preg_replace('~:(\w+)~', '(?P<$1>[^/]+)', $rule[0]); | |
// restructure the rules to make it more readable | |
// and append to Collection | |
Route::$rules[$this->base][$name] = array( | |
'pattern' => $rule[0], | |
'regex' => $regex, | |
'handler' => $rule[1], | |
'default' => isset($rule[2]) ? $rule[2] : array() | |
); | |
// create additional named rule index | |
// needed in url resolving process | |
Route::$named[$name] = array( | |
// delete all regex optional flag (whatever)? | |
'pattern' => preg_replace('~\((.*?)\)\?~', '$1', $rule[0]), | |
'default' => isset($rule[2]) ? $rule[2] : array() | |
); | |
} | |
} | |
/* end ./application/core/MY_Router.php */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |
class News extends MX_Controller { | |
public function category($category, $page) | |
{ | |
echo 'Looking for category name "'.$category.'", page "'.$page.'"'; | |
echo 'Linking back using ' . site_url(Route::to('news.category', array('category' => 'sports', 'page' => 15))); | |
} | |
} | |
/* End ./modules/news/controllers/news.php */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); | |
$route['default_controller'] = "home"; | |
$route['404_override'] = 'error/notfound'; | |
$route['error/404'] = $route['404_override']; | |
// ------------------------------------------------------------------------- | |
// Example - NEWS Module Route | |
Route::group('/news')->addRules(array( | |
'news.category' => array('/:category(/page/:page)?', 'news/category/:category/:page', array('page' => 1)), | |
'news.detail' => array('/:url', 'news/detail/:url') | |
)); | |
Route::admin('/news')->addRules(array( | |
'admin.news.list' => array('/page/:page', 'news/admin/news/page', array('page' => 1)), | |
'admin.news.add' => array('/add', 'news/admin/news/add'), | |
'admin.news.edit' => array('/edit/:id', 'news/admin/news/edit/:id'), | |
'admin.news.trash' => array('/trash/:id', 'news/admin/news/trash/:id'), | |
'admin.news.delete' => array('/delete/:id', 'news/admin/news/delete/:id'), | |
'admin.news.view' => array('/view/:id', 'news/admin/news/view/:id'), | |
'admin.news.edit' => array('/edit/:id', 'news/admin/news/edit/:id') | |
)); | |
Route::admin('/news/category')->addRules(array( | |
'admin.news.category.list' => array('/page/:page', 'news/admin/category/page/:page', array('page' => 1)), | |
'admin.news.category.add' => array('/add', 'news/admin/category/add'), | |
'admin.news.category.edit' => array('/edit/:id', 'news/admin/category/edit/:id'), | |
'admin.news.category.trash' => array('/trash/:id', 'news/admin/category/trash/:id'), | |
'admin.news.category.delete' => array('/delete/:id', 'news/admin/category/delete/:id') | |
)); | |
/* end ./application/config/routes.php */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment