layout | title | chapter | meta-description |
---|---|---|---|
default |
Request Flow |
2 |
Learn how Magento bootstraps itself and handles requests. |
Exam proportion: 7%.
- Check compilier configuration
- Include
Mage.php
- Setup core functions and autoloader
- Register the autoloader
Mage::run()
- Instantiate
Mage_Core_Model_App
- Instantiate the Config model
$app-run()
baseInit()
- load the base config and initialise cache.initModules()
- load module configuration.- Run all the required SQL install and upgrade scripts
- Setup the locale
initCurrentStore()
- load store configuration and instantiate the store modelinitRequest()
- load the request information into the model- Run all the required data install and upgrade scripts
- Dispatch the request
- Instantiate
The include path is set up and the autoloader is registered when the Mage.php
file is included in index.php
. Shortly after this occurs the autoloader is registered with spl_autoload_register
.
The base configuration of Magento is loaded in Mage_Core_Model_Config::loadBase
. It grabs the glob of app/etc/*.xml
which contains key config information, e.g. database credentials, the core module, the results of installation.
Database config is stored in app/etc/local.xml
and app/etc/config.xml
.
Mage_Core_Model_Config::loadModules
handles looping over each of the modules that exist in app/etc/modules/
and merging their own config.xml
files from their respective module directories.
The order that modules are loaded in is:
Mage_All.xml
Mage_*.xml
- Everything else
If a module depends on another, Magento makes sure it exists and loads its configuration first.
Modules are loaded after the base configuration but before store initialisation.
Module loading and SQL database upgrades are run when Mage_Core_Model_App::app()
is called but data upgrades are not. Whereas Mage_Core_Model_App::run()
completes all of the above. It does so in two phases.
-
Mage_Core_Model_Resource_Setup::applyAllUpdates()
- executed immediately after the module configuration is loaded and runs all the SQL install and update scripts. -
Mage_Core_Model_Resource_Setup::applyAllDataUpdates()
- executed after the store, locale and request models have been initialised and runs the data install and upgrade scripts.
In the Mage_Core_Model_App::run()
method, Magento sets up which store to use by:
<?php $this->_initCurrentStore($scopeCode, $scopeType); ?>
There are multiple ways to specify the current store.
- Environment variables
- Reorder store priorities
- GET parameter
__store
The environment variables are checked in index.php
:
<?php
/* Store or website code */
$mageRunCode = isset($_SERVER['MAGE_RUN_CODE']) ? $_SERVER['MAGE_RUN_CODE'] : '';
/* Run store or run website */
$mageRunType = isset($_SERVER['MAGE_RUN_TYPE']) ? $_SERVER['MAGE_RUN_TYPE'] : 'store';
?>
The request object is initialised in Mage_Core_Model_App
and the _initRequest()
method. getRequest()
and getResponse
are relevant.
The front controller performs the routing of the request to the appropriate controller. It loops over all of the registered routers, passing the request to each one of them to be matched against a controller capable of handling it. After the request has been dispatched, the front controller sends the response to the client.
controller_front_init_before
- Fired before adding the routers. It is useful for adding a router that takes precedence over any others.
controller_front_init_routers
- Fired after adding the routers, but before the default router is added. It is useful for adding general routers or modifying existing ones.
controller_front_send_response_before
- Fired before the response is sent out. It is useful for modifying the response data after the dispatch.
controller_front_send_response_after
- Fired after the response is sent out. It is useful for performing any tear down operations after the request has been dealt with.
There are two ways to add routes.
- Using configuration
<config>
<default>
<web>
<routers>
<{name}>
<area></area>
<class></class>
</{name}>
</routers>
</web>
</default>
</config>
- By observer the
controller_front_init_before
orcontroller_front_init_routers
events and injecting the router into the front controller.
The URL structure in Magento generally uses the format {base_url}/{front_name}/{controller}/{action}
.
Mage_Core_Controller_Varien_Router_Standard
parses the URLs in this format and maps them to a module used and the controller action to be executed.
URL rewrites happen in the Front controller before the routing. The database rewrites are checked and applied first, followed by the configuration (global->rewrite
) rewrites. Rewrites can either redirect the request using HTTP methods, update the request path (keeping the old one for reference) or completely replace the request path.
The most important fields in the core_url_rewrite
table are request_path
and target_path
which map the request to a rewrite.
Magento creates catalog requires using the catalog_url
indexer.
The requests are applied by the Mage_Core_Model_Url_Rewrite_Request
model. The request path is parsed to include any variation (with or without the trailing slash) and then looks up the request_path
column of the core_url_rewrite
table using the Mage_Core_Model_Url_Rewrite::loadByRequestPath()
method.
Built-in Magento routers (in the order that they are matched):
- Admin
- Collects all routes for the administration area
- Looks within
config.xml
for routes within admin.
- Standard
- Superclass of Admin
- Collects routes from within frontend routes defined in
config.xml
- CMS
- Routes CMS pages from identifiers
- Default
- This will always match.
- Routes error or 404 pages.
The standard router maps a path to an action by splitting it into base_url/frontname/controller/action
. The frontname
is then mapped to a module by way of the configuration files. The controller file is then located at `/path/to/module/base/controllers/{Name}Controller.php
Unmapped requests read the Default router where they are rewritten to a 404 page and get mapped by the Standard router on the next iteration.
Before dispatch, request module, controller, action and parameters are set. Then it is passed to the controller (all within the Standard router).
The store design (core/design_package
) is initialised in the controller preDispatch()
method. The package and theme configuration is then determined by the Mage_Core_Model_Design
.
Layout files get read ($layout->getUpdate()->load()
) when the controller calls $this->loadLayout()
. The same method also compiles the layout ($layout->generateXml()
) which processes the layout directives.
Output is rendered when the controller calls $this->renderLayout()
, which calls each of the blocks defined to output data e.g. output="toHtml"
in the definition, and merged their output into the response body.
To add a layout handle to be processed call
<?php Mage::getLayout()->getUpdate()->addHandle('new_handle'); ?>
Behind the scenes Mage_Core_Model_Layout_Update
loads the layout files and their XML while Mage_Core_Model_Layout
processes it.
Layout XML gets merged, first from modules, then local.xml
and then the database. The next step is to remove blocks or references as directed by the <remove>
element.
To add a layout file to be merged, add this to an extensions config.xml
file:
<config>
<{area}>
<layout>
<updates>
<{name}>
<file>{filename.xml}</file>
</{name}>
</updates>
</layout>
</{area}>
</config>
This file will then be searched for in app/design/{area}/{package}/{theme}/layout/{filename.xml}
Response content gets set by the $layout->renderLayout()
method. After the controller dispatch method returns, the Front Controller send the response.
The controller_front_send_response_before
event can be used to modify the response before sending. Subsequently, observing for the controller_front_send_response_after
event allows for cleaning up after if necessary.
If the output is not sent in a response object but printed out, it can prevent headers from being sent as it is unbuffered.
There are two types of redirects that can be used in a controller action.
_redirect()
- This performs a HTTP redirect
_forward()
- This redirects internally within the application to another controller and/or action.