Certificated magento

2.4) Describe the role of the front controller

 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:
 
 
/**
     * 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.
 
 
    /**
     * 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:
 
 /**
     * 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:
 
 
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.
 
Next, 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):
 
 
$routersInfo = Mage::app()->getStore()->getConfig(self::XML_STORE_ROUTERS_PATH);
Core/etc/config.xml
 
<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:
 
 
        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:
 
 
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:
 
cms/etc/config.xml
<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:
 
 
    /**
     * 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):
 
 
$default = new Mage_Core_Controller_Varien_Router_Default();
$this->addRouter('default', $default);
At the end we have routs processing order:
 
  • admin
  •  
  • standard
  •  
  • cms
  •  
  • default
 
Module route is determined in its config.xml
 
For a frontend:
 
 
    <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).
 
 
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:
 
 
$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.
 
 
$request->setPathInfo()->setDispatched(false);
 
Rewrite is chosen from the database for the current request:
 
 
         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:
 
 
        Varien_Profiler::start('mage::dispatch::config_url_rewrite');
        $this->rewrite();
        Varien_Profiler::stop('mage::dispatch::config_url_rewrite');
Rewrite controllers are determined here:
 
 
<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:
 
 
      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.
 
 
$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:
 
 
       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));
 

0 Bình luận

Trở về
  • 1.12) Set up a cron job
  • 1.12) Set up a cron job

    Let’s start with server setup.   As any complex system, Magento has a lot of tasks that need to be executed...