Magento Controller Initialization and Flow

In this blog post we are going to see in detail how magento loads controller, action based on URL
Files to Refer
1. Mage/Core/Model/App.php
2. Mage/Core/Controller/Varien/Front.php
3. Mage/Core/Controller/Varien/Router/Standard.php

As we have seen before, the “run()” function in Mage_Core_Model_App class is where the control comes when we open any URL.
Here we see the line

$this->getFrontController()->dispatch();

which is responsible for loading the controller and calling the action.

The function “getFrontController()” create a object for class Mage_Core_Controller_Varien_Front and calls the “init()” method.

Lets see working of “init()” function in detail

First important line in “init()” function is

$routersInfo = Mage::app()->getStore()->getConfig(self::XML_STORE_ROUTERS_PATH);

This basically returns

Array
(
    [admin] => Array
        (
            [area] => admin
            [class] => Mage_Core_Controller_Varien_Router_Admin
        )

    [standard] => Array
        (
            [area] => frontend
            [class] => Mage_Core_Controller_Varien_Router_Standard
        )

)

This data is defined in “app/code/core/Mage/Core/etc/config.xml” file
So this returns two router classes for admin and frontend area.
Next we see

$router = new $routerInfo['class'];
                if (isset($routerInfo['area'])) {
                    $router->collectRoutes($routerInfo['area'], $routerCode);
                }
                $this->addRouter($routerCode, $router);

This code creates a new object of each of router class and calls the “collectRoutes()” function in it.
So lets open the class “Mage_Core_Controller_Varien_Router_Standard” and see the “collectRoutes()” function.
The first line here is to create the xpath “frontend/routers/args/module”
This is the same routes we define in our module config.xml files

<routers>
            <checkout>
                <use>standard</use>
                <args>
                    <module>Mage_Checkout</module>
                    <frontName>checkout</frontName>
                </args>
            </checkout>
        </routers>

There is also a check for “routerName”

$use = (string)$routerConfig->use;
if ($use == $useRouterName) {

here the “use” tag in xml is checked to standard or admin.

Finally this function is called

$this->addModule($frontName, $modules, $routerName);

which adds the route and module to an array for further use.

Now lets go back to our original function

$this->getFrontController()->dispatch();

Above we have seen the first part i.e “getFrontController()” now lets look at the “dispatch()” function.

If you open the class “Mage_Core_Controller_Varien_Front” class, you will see the “dispatch()” function there.

The first important function here is

$this->_checkBaseUrl($request);

this checks if the current opened in the browser is same as the base url set in system configuration or not.

Next important line we have

$this->_getRequestRewriteController()->rewrite();

We will look this line in detail a little later, but this line mainly check for any URL rewriting we might have done at database level (Admin -> Catalog -> URL Management) or any URL rewrites done in config.xml

Next for each router we have “match()” function getting called.
If you look at “match()” function in Mage_Core_Controller_Varien_Router_Standard. Lets see in detail how the match() function works

Here the url is broken upto 3 parts; modules, controller, action.

        $path = trim($request->getPathInfo(), '/');

        if ($path) {
            $p = explode('/', $path);
        } else {
            $p = explode('/', $this->_getDefaultPath());
        }

Next we have

$module = $p[0];
$modules = $this->getModuleByFrontName($module);

above we see based on the first url part, module name is determined.
Next

$controller = $p[1];
$action = !empty($p[2]) ? $p[2] : $front->getDefault('action');

So above controller and action are set.
Next

$this->_checkShouldBeSecure($request, '/'.$module.'/'.$controller.'/'.$action);

This if the URL should be secure (https) or not. If it should be it redirects to https url.
Next

$controllerClassName = $this->_validateControllerClassName($realModule, $controller);

This function generates the controller file path (full directory path) using module name and controller name. Check if the file exists and class is already loaded or not. If not loading “include()” the file.

After this the action function is checked, if its present in the controller or not. Finally all parameters are set into the request object using “setParam()” function and then “dispatch()” function is called in the controller.

We know that every controller in magento extension the Mage_Core_Controller_Front_Action class which in turn extensions the Mage_Core_Controller_Varien_Action class. In the “Mage_Core_Controller_Varien_Action” class you will find the “dispatch()” method. Lets see the “dispatch()” function in detail

$actionMethodName = $this->getActionMethodName($action);
if (!method_exists($this, $actionMethodName)) {
  $actionMethodName = 'norouteAction';
}
$this->preDispatch();
$this->$actionMethodName();
$this->postDispatch();

Above is the entire life cycle of magento calling action of a controller when we open a URL in the browser