Route determination starts with the search for the current route compliance with the routes, determined in the system. The process begins here:

app/code/core/Mage/Core/Controller/Varien/Front.php



Varien_Profiler::start('mage::dispatch::routers_match'); $i = 0; while (!$request->isDispatched() && $i++<100) { foreach ($this->_routers as $router) { if ($router->match($this->getRequest())) { break; } } } Varien_Profiler::stop('mage::dispatch::routers_match'); if ($i>100) { Mage::throwException('Front controller reached 100 router match iterations'); } // This event gives possibility to launch something before sending output (allow cookie setting) Mage::dispatchEvent('controller_front_send_response_before', array('front'=>$this)); Varien_Profiler::start('mage::app::dispatch::send_response'); $this->getResponse()->sendResponse(); Varien_Profiler::stop('mage::app::dispatch::send_response'); Mage::dispatchEvent('controller_front_send_response_after', array('front'=>$this)); return $this; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Varien_Profiler:: start ( 'mage::dispatch::routers_match' ) ; $i = 0 ; while ( ! $request -> isDispatched ( ) && $i ++ < 100 ) { foreach ( $this -> _routers as $router ) { if ( $router -> match ( $this -> getRequest ( ) ) ) { break ; } } } Varien_Profiler:: stop ( 'mage::dispatch::routers_match' ) ; if ( $i > 100 ) { Mage:: throwException ( 'Front controller reached 100 router match iterations' ) ; } // This event gives possibility to launch something before sending output (allow cookie setting) Mage:: dispatchEvent ( 'controller_front_send_response_before' , array ( 'front' = > $this ) ) ; Varien_Profiler:: start ( 'mage::app::dispatch::send_response' ) ; $this -> getResponse ( ) -> sendResponse ( ) ; Varien_Profiler:: stop ( 'mage::app::dispatch::send_response' ) ; Mage:: dispatchEvent ( 'controller_front_send_response_after' , array ( 'front' = > $this ) ) ; return $this ;



There are 4 routes defined in Magento by default:

Mage_Core_Controller_Varien_Router_Admin

Mage_Core_Controller_Varien_Router_Standard

Mage_Cms_Controller_Router

Mage_Core_Controller_Varien_Router_Default

As we know from Magento Front Controller Pattern article, $this->_routers variable contains all the defined routes. The searching will be thereby performed in this array. It will be carried out among all the routes and will stop at the first match found. If no matches are found, the route defined for 404 will be processed or the ‘Front controller reached 100 router match iterations’ message will be displayed:



if ($i>100) { Mage::throwException('Front controller reached 100 router match iterations'); } 1 2 3 if ( $i > 100 ) { Mage:: throwException ( 'Front controller reached 100 router match iterations' ) ; }



Main steps of the routing process:

module determination

controller determination

action to perform detection

data for the current request detection

Let’s take a look at the routes initialization:



Varien_Profiler::start('mage::app::init_front_controller::collect_routers'); foreach ($routersInfo as $routerCode => $routerInfo) { if (isset($routerInfo['disabled']) && $routerInfo['disabled']) { continue; } if (isset($routerInfo['class'])) { $router = new $routerInfo['class']; if (isset($routerInfo['area'])) { $router->collectRoutes($routerInfo['area'], $routerCode); } $this->addRouter($routerCode, $router); } } Varien_Profiler::stop('mage::app::init_front_controller::collect_routers'); Mage::dispatchEvent('controller_front_init_routers', array('front'=>$this)); // Add default router at the last $default = new Mage_Core_Controller_Varien_Router_Default(); $this->addRouter('default', $default); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 Varien_Profiler:: start ( 'mage::app::init_front_controller::collect_routers' ) ; foreach ( $routersInfo as $routerCode = > $routerInfo ) { if ( isset ( $routerInfo [ 'disabled' ] ) && $routerInfo [ 'disabled' ] ) { continue ; } if ( isset ( $routerInfo [ 'class' ] ) ) { $router = new $routerInfo [ 'class' ] ; if ( isset ( $routerInfo [ 'area' ] ) ) { $router -> collectRoutes ( $routerInfo [ 'area' ] , $routerCode ) ; } $this -> addRouter ( $routerCode , $router ) ; } } Varien_Profiler:: stop ( 'mage::app::init_front_controller::collect_routers' ) ; Mage:: dispatchEvent ( 'controller_front_init_routers' , array ( 'front' = > $this ) ) ; // Add default router at the last $default = new Mage_Core_Controller_Varien_Router_Default ( ) ; $this -> addRouter ( 'default' , $default ) ;



Administrative routes are being initialized first:

app/code/core/Mage/Core/Controller/Varien/Router/Admin.php



public function collectRoutes($configArea, $useRouterName) { if ((string)Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_USE_CUSTOM_ADMIN_PATH)) { $customUrl = (string)Mage::getConfig()->getNode(Mage_Adminhtml_Helper_Data::XML_PATH_CUSTOM_ADMIN_PATH); $xmlPath = Mage_Adminhtml_Helper_Data::XML_PATH_ADMINHTML_ROUTER_FRONTNAME; if ((string)Mage::getConfig()->getNode($xmlPath) != $customUrl) { Mage::getConfig()->setNode($xmlPath, $customUrl, true); } } parent::collectRoutes($configArea, $useRouterName); } 1 2 3 4 5 6 7 8 9 10 11 public function collectRoutes ( $configArea , $useRouterName ) { if ( ( string ) Mage:: getConfig ( ) -> getNode ( Mage_Adminhtml_Helper_Data:: XML_PATH_USE_CUSTOM_ADMIN_PATH ) ) { $customUrl = ( string ) Mage:: getConfig ( ) -> getNode ( Mage_Adminhtml_Helper_Data:: XML_PATH_CUSTOM_ADMIN_PATH ) ; $xmlPath = Mage_Adminhtml_Helper_Data:: XML_PATH_ADMINHTML_ROUTER_FRONTNAME ; if ( ( string ) Mage:: getConfig ( ) -> getNode ( $xmlPath ) != $customUrl ) { Mage:: getConfig ( ) -> setNode ( $xmlPath , $customUrl , true ) ; } } parent :: collectRoutes ( $configArea , $useRouterName ) ; }



The route, administrative part is accessible at, is verified here. It is also checked if it is redefined or not. Considering Admin is the extension of Standard, the following is next executed:



parent::collectRoutes($configArea, $useRouterName); app/code/core/Mage/Core/Controller/Varien/Router/Standard.php public function collectRoutes($configArea, $useRouterName) { $routers = array(); $routersConfigNode = Mage::getConfig()->getNode($configArea.'/routers'); if($routersConfigNode) { $routers = $routersConfigNode->children(); } foreach ($routers as $routerName=>$routerConfig) { $use = (string)$routerConfig->use; if ($use == $useRouterName) { $modules = array((string)$routerConfig->args->module); if ($routerConfig->args->modules) { foreach ($routerConfig->args->modules->children() as $customModule) { if ($customModule) { if ($before = $customModule->getAttribute('before')) { $position = array_search($before, $modules); if ($position === false) { $position = 0; } array_splice($modules, $position, 0, (string)$customModule); } elseif ($after = $customModule->getAttribute('after')) { $position = array_search($after, $modules); if ($position === false) { $position = count($modules); } array_splice($modules, $position+1, 0, (string)$customModule); } else { $modules[] = (string)$customModule; } } } } $frontName = (string)$routerConfig->args->frontName; $this->addModule($frontName, $modules, $routerName); } } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 parent :: collectRoutes ( $configArea , $useRouterName ) ; app / code / core / Mage / Core / Controller / Varien / Router / Standard . php public function collectRoutes ( $configArea , $useRouterName ) { $routers = array ( ) ; $routersConfigNode = Mage:: getConfig ( ) -> getNode ( $configArea . '/routers' ) ; if ( $routersConfigNode ) { $routers = $routersConfigNode -> children ( ) ; } foreach ( $routers as $routerName = > $routerConfig ) { $use = ( string ) $routerConfig -> use ; if ( $use == $useRouterName ) { $modules = array ( ( string ) $routerConfig -> args -> module ) ; if ( $routerConfig -> args -> modules ) { foreach ( $routerConfig -> args -> modules -> children ( ) as $customModule ) { if ( $customModule ) { if ( $before = $customModule -> getAttribute ( 'before' ) ) { $position = array_search ( $before , $modules ) ; if ( $position === false ) { $position = 0 ; } array_splice ( $modules , $position , 0 , ( string ) $customModule ) ; } elseif ( $after = $customModule -> getAttribute ( 'after' ) ) { $position = array_search ( $after , $modules ) ; if ( $position === false ) { $position = count ( $modules ) ; } array_splice ( $modules , $position + 1 , 0 , ( string ) $customModule ) ; } else { $modules [ ] = ( string ) $customModule ; } } } } $frontName = ( string ) $routerConfig -> args -> frontName ; $this -> addModule ( $frontName , $modules , $routerName ) ; } } }



All the routes defined in the configuration are picked and processed here, considering before and after events. _modules and _routes arrays of modules and routes correspondingly for the current route type are also filled:

app/code/core/Mage/Core/Controller/Varien/Router/Standard.php



public function addModule($frontName, $moduleName, $routeName) { $this->_modules[$frontName] = $moduleName; $this->_routes[$routeName] = $frontName; return $this; } 1 2 3 4 5 6 public function addModule ( $frontName , $moduleName , $routeName ) { $this -> _modules [ $frontName ] = $moduleName ; $this -> _routes [ $routeName ] = $frontName ; return $this ; }



Next, this route object is added to the general routes list:

app/code/core/Mage/Core/Controller/Varien/Front.php



$router = new $routerInfo['class']; if (isset($routerInfo['area'])) { $router->collectRoutes($routerInfo['area'], $routerCode); } $this->addRouter($routerCode, $router); /** * Adding new router * * @param string $name * @param Mage_Core_Controller_Varien_Router_Abstract $router * @return Mage_Core_Controller_Varien_Front */ public function addRouter($name, Mage_Core_Controller_Varien_Router_Abstract $router) { $router->setFront($this); $this->_routers[$name] = $router; return $this; } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $router = new $routerInfo [ 'class' ] ; if ( isset ( $routerInfo [ 'area' ] ) ) { $router -> collectRoutes ( $routerInfo [ 'area' ] , $routerCode ) ; } $this -> addRouter ( $routerCode , $router ) ; /** * Adding new router * * @param string $name * @param Mage_Core_Controller_Varien_Router_Abstract $router * @return Mage_Core_Controller_Varien_Front */ public function addRouter ( $name , Mage_Core_Controller_Varien_Router_Abstract $router ) { $router -> setFront ( $this ) ; $this -> _routers [ $name ] = $router ; return $this ; }



Standard routes are initialized the same way.

It can be demonstrated easier as follows:



Partner With Us Let's discuss how to grow your business. Get a Free Quote.

$router = new Mage_Core_Controller_Varien_Router_Admin(); $router->collectRoutes('admin','admin'); $this->addRouter('admin',$router); $router = new Mage_Core_Controller_Varien_Router_Standard(); $router->collectRoutes('frontend','standard'); $this->addRouter('standard',$router); 1 2 3 4 5 6 7 $router = new Mage_Core_Controller_Varien_Router_Admin ( ) ; $router -> collectRoutes ( 'admin' , 'admin' ) ; $this -> addRouter ( 'admin' , $router ) ; $router = new Mage_Core_Controller_Varien_Router_Standard ( ) ; $router -> collectRoutes ( 'frontend' , 'standard' ) ; $this -> addRouter ( 'standard' , $router ) ;



CMS (“static”) routes are added via controller_front_init_routers event next:

app/code/core/Mage/Cms/etc/config.xml



<events> <controller_front_init_routers> <observers> <cms> <class>Mage_Cms_Controller_Router</class> <method>initControllerRouters</method> </cms> </observers> </controller_front_init_routers> </events> 1 2 3 4 5 6 7 8 9 10 < events > < controller_front_init_routers > < observers > < cms > < class > Mage_Cms_Controller_Router < / class > < method > initControllerRouters < / method > < / cms > < / observers > < / controller_front_init_routers > < / events >



app/code/core/Mage/Cms/Controller/Router.php



public function initControllerRouters($observer) { /* @var $front Mage_Core_Controller_Varien_Front */ $front = $observer->getEvent()->getFront(); $front->addRouter('cms', $this); } 1 2 3 4 5 6 7 public function initControllerRouters ( $observer ) { /* @var $front Mage_Core_Controller_Varien_Front */ $front = $observer -> getEvent ( ) -> getFront ( ) ; $front -> addRouter ( 'cms' , $this ) ; }



After all, Default 404/no-route routes:



// Add default router at the last $default = new Mage_Core_Controller_Varien_Router_Default(); $this->addRouter('default', $default); 1 2 3 // Add default router at the last $default = new Mage_Core_Controller_Varien_Router_Default ( ) ; $this -> addRouter ( 'default' , $default ) ;



After routes initialization, searching for appropriate things is performed:



while (!$request->isDispatched() && $i++<100) { foreach ($this->_routers as $router) { if ($router->match($this->getRequest())) { break; } } } 1 2 3 4 5 6 7 while ( ! $request -> isDispatched ( ) && $i ++ < 100 ) { foreach ( $this -> _routers as $router ) { if ( $router -> match ( $this -> getRequest ( ) ) ) { break ; } } }



As Admin routes are an extension to Standard, we first look more closely at Standard. It’s primarily checked if the administrative interface is active:



/** * checking if this admin if yes then we don't use this router * * @return bool */ protected function _beforeModuleMatch() { if (Mage::app()->getStore()->isAdmin()) { return false; } return true; } 1 2 3 4 5 6 7 8 9 10 11 12 /** * checking if this admin if yes then we don't use this router * * @return bool */ protected function _beforeModuleMatch ( ) { if ( Mage:: app ( ) -> getStore ( ) -> isAdmin ( ) ) { return false ; } return true ; }



Default route is defined next:



public function fetchDefault() { $this->getFront()->setDefault(array( 'module' => 'core', 'controller' => 'index', 'action' => 'index' )); } 1 2 3 4 5 6 7 8 public function fetchDefault ( ) { $this -> getFront ( ) -> setDefault ( array ( 'module' = > 'core' , 'controller' = > 'index' , 'action' = > 'index' ) ) ; }



The current request goes next; it is taken to pieces:



$front = $this->getFront(); $path = trim($request->getPathInfo(), '/'); if ($path) { $p = explode('/', $path); } else { $p = explode('/', $this->_getDefaultPath()); } 1 2 3 4 5 6 7 8 $front = $this -> getFront ( ) ; $path = trim ( $request -> getPathInfo ( ) , '/' ) ; if ( $path ) { $p = explode ( '/' , $path ) ; } else { $p = explode ( '/' , $this -> _getDefaultPath ( ) ) ; }



For example, for the following path: catalog/category/view/id/10 we get:



$p = array( 0 => catalog, 1 => category, 2 => view, 3 => id, 4 => 10 ); 1 2 3 4 5 6 7 $p = array ( 0 = > catalog , 1 = > category , 2 = > view , 3 = > id , 4 = > 10 ) ;



First 3 elements are principal here; they indicate module, controller and action for the current request.

Next, the module is determined from its frontName:



/** * Searching router args by module name from route using it as key */ $modules = $this->getModuleByFrontName($module); 1 2 3 4 /** * Searching router args by module name from route using it as key */ $modules = $this -> getModuleByFrontName ( $module ) ;



The controller and the action for the current request are thereafter defined:



// get controller name if ($request->getControllerName()) { $controller = $request->getControllerName(); } else { if (!empty($p[1])) { $controller = $p[1]; } else { $controller = $front->getDefault('controller'); $request->setAlias( Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS, ltrim($request->getOriginalPathInfo(), '/') ); } } // get action name if (empty($action)) { if ($request->getActionName()) { $action = $request->getActionName(); } else { $action = !empty($p[2]) ? $p[2] : $front->getDefault('action'); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // get controller name if ( $request -> getControllerName ( ) ) { $controller = $request -> getControllerName ( ) ; } else { if ( ! empty ( $p [ 1 ] ) ) { $controller = $p [ 1 ] ; } else { $controller = $front -> getDefault ( 'controller' ) ; $request -> setAlias ( Mage_Core_Model_Url_Rewrite:: REWRITE_REQUEST_PATH_ALIAS , ltrim ( $request -> getOriginalPathInfo ( ) , '/' ) ) ; } } // get action name if ( empty ( $action ) ) { if ( $request -> getActionName ( ) ) { $action = $request -> getActionName ( ) ; } else { $action = ! empty ( $p [ 2 ] ) ? $p [ 2 ] : $front -> getDefault ( 'action' ) ; } }



It’s also checked if the connection is safe and if the controller file exists:



//checking if this place should be secure $this->_checkShouldBeSecure($request, '/'.$module.'/'.$controller.'/'.$action); $controllerClassName = $this->_validateControllerClassName($realModule, $controller); if (!$controllerClassName) { continue; } 1 2 3 4 5 6 7 //checking if this place should be secure $this -> _checkShouldBeSecure ( $request , '/' . $module . '/' . $controller . '/' . $action ) ; $controllerClassName = $this -> _validateControllerClassName ( $realModule , $controller ) ; if ( ! $controllerClassName ) { continue ; }



Controller object is created next. It’s checked if the specified action exists in the controller:



// instantiate controller class $controllerInstance = Mage::getControllerInstance($controllerClassName, $request, $front->getResponse()); if (!$controllerInstance->hasAction($action)) { 1 2 3 4 // instantiate controller class $controllerInstance = Mage:: getControllerInstance ( $controllerClassName , $request , $front -> getResponse ( ) ) ; if ( ! $controllerInstance -> hasAction ( $action ) ) {





continue; } 1 2 continue ; }



It’s after all flagged that the route is processed. Module, controller and action are defined and action is performed for the current request.



$request->setModuleName($module); $request->setControllerName($controller); $request->setActionName($action); $request->setControllerModule($realModule); // set parameters from pathinfo for ($i = 3, $l = sizeof($p); $i < $l; $i += 2) { $request->setParam($p[$i], isset($p[$i+1]) ? urldecode($p[$i+1]) : ''); } // dispatch action $request->setDispatched(true); $controllerInstance->dispatch($action); return true; 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 $request -> setModuleName ( $module ) ; $request -> setControllerName ( $controller ) ; $request -> setActionName ( $action ) ; $request -> setControllerModule ( $realModule ) ; // set parameters from pathinfo for ( $i = 3 , $l = sizeof ( $p ) ; $i < $l ; $i += 2 ) { $request -> setParam ( $p [ $i ] , isset ( $p [ $i + 1 ] ) ? urldecode ( $p [ $i + 1 ] ) : '' ) ; } // dispatch action $request -> setDispatched ( true ) ; $controllerInstance -> dispatch ( $action ) ; return true ;



Control returns to dispatch FrontController method, where “output” is defined for the current request.