Magento uses the Front Controller pattern for the following purposes:
- Receiving and processing browser data, transferring it to other system elements;
- Defining controller and proper action to perform using routes;
- Displaying browser-requested data using blocks, templates and model data.
Front Controller main structure is stored in Core module:
Mage/Core/Controller/Varien/Front.
Let’s review the basic steps of Front Controller initialization.
The first call is performed in Mage_Core_Model_App constructor:
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 |
/** * Run application. Run process responsible for request processing and sending response. * List of supported parameters: * scope_code - code of default scope (website/store_group/store code) * scope_type - type of default scope (website/group/store) * options - configuration options * * @param array $params application run parameters * @return Mage_Core_Model_App */ public function run($params) { $options = isset($params['options']) ? $params['options'] : array(); $this->baseInit($options); Mage::register('application_params', $params); if ($this->_cache->processRequest()) { $this->getResponse()->sendResponse(); } else { $this->_initModules(); $this->loadAreaPart(Mage_Core_Model_App_Area::AREA_GLOBAL, Mage_Core_Model_App_Area::PART_EVENTS); if ($this->_config->isLocalConfigLoaded()) { $scopeCode = isset($params['scope_code']) ? $params['scope_code'] : ''; $scopeType = isset($params['scope_type']) ? $params['scope_type'] : 'store'; $this->_initCurrentStore($scopeCode, $scopeType); $this->_initRequest(); Mage_Core_Model_Resource_Setup::applyAllDataUpdates(); } $this->getFrontController()->dispatch(); } return $this; } |
wherein getFrontController method is called. Before current request processing starts, Mage_Core_Controller_Varien_Front object is created and its initialization is called.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** * Initialize application front controller * * @return Mage_Core_Model_App */ protected function _initFrontController() { $this->_frontController = new Mage_Core_Controller_Varien_Front(); Mage::register('controller', $this->_frontController); Varien_Profiler::start('mage::app::init_front_controller'); $this->_frontController->init(); Varien_Profiler::stop('mage::app::init_front_controller'); return $this; } |
Let’s take a closer look at the init method:
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 |
/** * Init Front Controller * * @return Mage_Core_Controller_Varien_Front */ public function init() { Mage::dispatchEvent('controller_front_init_before', array('front'=>$this)); $routersInfo = Mage::app()->getStore()->getConfig(self::XML_STORE_ROUTERS_PATH); 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); return $this; } |
Controller_front_init_before event is initially called:
1 |
Mage::dispatchEvent('controller_front_init_before', array('front'=>$this)); |
It can be used to set the $routerInfo[‘disabled’] flag and to determine routes your way.
Magento 2 Development
Take your online store to the next level with BelVG Magento 2 Development
Visit the pageNext, routes, determined in config.xml in web/routes section (global configuration), are selected. At this application initialization stage, these are admin and standard sections, i.e. admin routing areas are determined:
(Mage_Core_Controller_Varien_Router_Admin) and standard (Mage_Core_Controller_Varien_Router_Standard):
1 |
$routersInfo = Mage::app()->getStore()->getConfig(self::XML_STORE_ROUTERS_PATH); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<web> <!-- ... --> <routers> <admin> <area>admin</area> <class>Mage_Core_Controller_Varien_Router_Admin</class> </admin> <standard> <area>frontend</area> <class>Mage_Core_Controller_Varien_Router_Standard</class> </standard> </routers> <!-- ... --> </web> |
Next, all active modules are processed and specified ones are added to their routes configurations:
1 2 3 4 5 6 7 8 9 10 11 12 |
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); } } |
Next, controller_front_init_routers event is called:
1 |
Mage::dispatchEvent('controller_front_init_routers', array('front'=>$this)); |
With the help of this event CMS module adds CMS routing area. We add our own routes as well.
Specified event:
1 2 3 4 5 6 7 8 9 10 11 12 |
<global> <events> <controller_front_init_routers> <observers> <cms> <class>Mage_Cms_Controller_Router</class> <method>initControllerRouters</method> </cms> </observers> </controller_front_init_routers> </events> </global> |
method itself:
1 2 3 4 5 6 7 8 9 10 11 12 |
/** * Initialize Controller Router * * @param Varien_Event_Observer $observer */ public function initControllerRouters($observer) { /* @var $front Mage_Core_Controller_Varien_Front */ $front = $observer->getEvent()->getFront(); $front->addRouter('cms', $this); } |
Default route is added after all (Mage_Core_Controller_Varien_Router_Default):
1 2 |
$default = new Mage_Core_Controller_Varien_Router_Default(); $this->addRouter('default', $default);<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;"> </span> |
At the end we have routs processing order:
admin
standard
cms
default
Module route is determined in its config.xml
For a frontend:
1 2 3 4 5 6 7 8 9 10 11 |
<frontend> <routers> <mymodule> <use>standard</use> <args> <module>My_Module</module> <frontName>mymodule</frontName> </args> </mymodule> </routers> </frontend> |
Frontend and Admin routs should differ.
After routes are formed, current browser request processing route is being determined (dispatch).
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 |
public function dispatch() { $request = $this->getRequest(); // If pre-configured, check equality of base URL and requested URL $this->_checkBaseUrl($request); $request->setPathInfo()->setDispatched(false); if (!$request->isStraight()) { Varien_Profiler::start('mage::dispatch::db_url_rewrite'); Mage::getModel('core/url_rewrite')->rewrite(); Varien_Profiler::stop('mage::dispatch::db_url_rewrite'); } Varien_Profiler::start('mage::dispatch::config_url_rewrite'); $this->rewrite(); Varien_Profiler::stop('mage::dispatch::config_url_rewrite'); 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; } |
Main application address is checked:
1 |
$this->_checkBaseUrl($request); |
Basic variables are prepared and flag of route correspondence in false is set. It determines if search should be continued or finished.
Partner With Us
Let's discuss how to grow your business. Get a Free Quote.
1 |
$request->setPathInfo()->setDispatched(false); |
Rewrite is chosen from the database for the current request:
1 2 3 4 5 |
if (!$request->isStraight()) { Varien_Profiler::start('mage::dispatch::db_url_rewrite'); Mage::getModel('core/url_rewrite')->rewrite(); Varien_Profiler::stop('mage::dispatch::db_url_rewrite'); } |
If there is a match, the address, corresponding to this rewrite, is followed. This is the custom url mechanism.
We also loop through rewrite, determined in global/routes configuration section:
1 2 3 |
Varien_Profiler::start('mage::dispatch::config_url_rewrite'); $this->rewrite(); Varien_Profiler::stop('mage::dispatch::config_url_rewrite'); |
Rewrite controllers are determined here:
1 2 3 4 5 6 7 8 9 10 11 |
<global> <rewrite> <!-- This is a class name for your controller --> <mynamespace_mymodule_checkout_cart> <!—Original controller route to be replaced --> <from><![CDATA[#^/checkout/cart/#]]></from> <!—Our controller route --> <to>/mymodule/checkout_cart/</to> </mynamespace_mymodule_checkout_cart> </rewrite> </global> |
Next, corresponding controller is determined and required action is performed:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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'); } |
Match search among all the known routes $this->_routers is performed.
1 |
$router->match($this->getRequest()) |
As soon as controller match is found, it is initialized and specified action or default action is performed (unless the action is determined directly in the request). Our later articles will explain routes as well as routes processing in greater detail.
As may be seen from the source code, the maximum number of attempts may not exceed 100.
Next, current request contents, including events before and after displaying setting, are prepared to be sent to the browser. Displaying can be prepared and changed in them correspondingly:
1 2 3 4 5 |
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)); |
Magento Custom Development
Take your online store to the next level with BelVG Magento Custom Development
Visit the page
Thank you very much
Nofel,
I mentioned how to disable admin routers just as an experiment. The routers were disabled through event – to repeat it, you need to create a module where you should define the event that was described in the article. But it is not recommended to disable admin routers because in this case the admin part of Magento will not work . Most probably your problem was not caused by disabling routers. We need more details to find out what happened and to be able to answer your question.
I am totally new to magento and i have a router error while my host upgraded the server and now i am stuck.I see you have mentioned how to disable routers by
public function controller_front_init_before(Varien_Event_Observer $observer)
{
//Disable admin
Mage::app()->getStore()->setConfig(‘web/routers/admin/disabled’, ‘disabled’);
//Disable standard
Mage::app()->getStore()->setConfig(‘web/routers/standard/disabled’, ‘disabled’);
}
but where and how to place it. pls guide me
Thanks, fixed.
I see your code pretty messed up. I think you had a problem with your Crayon plugin.
Diogo Santiago,
You can create the event using code similar to the following piece:
Parameters would rather be specified with local.xml, config.xml files.
Nice Article… How can i use controller_front_init_before to disable routers ? The routerInfo variable is created after this event is dispatched….
Thanks, waiting for continue!