Our another Magento certification-dedicated article describes the steps for application initialization.
Magento initialization process starts in index.php (with the exception of Magento integrated with some other sites or CMS).
Let’s take a look at the code of this file. Magento developers made their comments using multi line comment and PHPDoc style comments, so for my own comments I’ll use one line style (so called c++ style) comments.
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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
// Magento checks whether your PHP version is older than 5.2.0 // if not, error message is being displayed; you are suggested to install it once again and exit. if (version_compare(phpversion(), '5.2.0', '<')===true) { echo '<div style="font:12px/1.35em arial, helvetica, sans-serif;"> <div style="margin:0 0 25px 0; border-bottom:1px solid #ccc;"> <h3 style="margin:0; font-size:1.7em; font-weight:normal; text-transform:none; text-align:left; color:#2f2f2f;"> Whoops, it looks like you have an invalid PHP version.</h3></div><p>Magento supports PHP 5.2.0 or newer. <a href="http://www.magentocommerce.com/install" target="">Find out</a> how to install</a> Magento using PHP-CGI as a work-around.</p></div>'; exit; } /** * Error reporting */ error_reporting(E_ALL | E_STRICT); /** * Compilation includes configuration file */ define('MAGENTO_ROOT', getcwd()); // Include of compiler configuration // If compiler is enabled in System -> Tools -> Compilation // this will change loading pathes // Magento classes will be put in one 'src' folder $compilerConfig = MAGENTO_ROOT . '/includes/config.php'; if (file_exists($compilerConfig)) { include $compilerConfig; } // Include (require_once) of Mage.php file // If file doesn't exist redirect to downoader // If it also doesn't exist show error message $mageFilename = MAGENTO_ROOT . '/app/Mage.php'; $maintenanceFile = 'maintenance.flag'; if (!file_exists($mageFilename)) { if (is_dir('downloader')) { header("Location: downloader"); } else { echo $mageFilename." was not found"; } exit; } if (file_exists($maintenanceFile)) { include_once dirname(__FILE__) . '/errors/503.php'; exit; } require_once $mageFilename; //Enable Varien profiler by uncommenting this line #Varien_Profiler::enable(); // Set Magento in developer Mode // More info in Alan Storm's article http://alanstorm.com/magento_exception_handling_developer_mode if (isset($_SERVER['MAGE_IS_DEVELOPER_MODE'])) { Mage::setIsDeveloperMode(true); } #ini_set('display_errors', 1); umask(0); /* Store or website code */ // Magento accepts store code // If you don't specify anything it will use 'default' $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'; // app/Mage.php run() method // Main application entry point Mage::run($mageRunCode, $mageRunType); |
Now we should dig into app/Mage.php. It contains about 1000 lines (to be precise, it’s 989), so we will explore the most important things only. However, I think it’s a good idea for you to open it and analyze the whole file.
At the beginning of the file Magento checks if Compilation mode was enabled. If compiler is not enabled, Magento will include default paths, load code pools, load app/code/core/Mage/functions.php (if it’s not overwritten in local or community pool), load lib/Varien/Autoload.php and finally call Varien_Autoload::register() 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 |
define('DS', DIRECTORY_SEPARATOR); define('PS', PATH_SEPARATOR); define('BP', dirname(dirname(__FILE__))); Mage::register('original_include_path', get_include_path()); if (defined('COMPILER_INCLUDE_PATH')) { $appPath = COMPILER_INCLUDE_PATH; set_include_path($appPath . PS . Mage::registry('original_include_path')); include_once COMPILER_INCLUDE_PATH . DS . "Mage_Core_functions.php"; include_once COMPILER_INCLUDE_PATH . DS . "Varien_Autoload.php"; } else { /** * Set include path */ $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'local'; $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'community'; $paths[] = BP . DS . 'app' . DS . 'code' . DS . 'core'; $paths[] = BP . DS . 'lib'; $appPath = implode(PS, $paths); set_include_path($appPath . PS . Mage::registry('original_include_path')); include_once "Mage/Core/functions.php"; include_once "Varien/Autoload.php"; } Varien_Autoload::register(); |
In register() method from lib/Varien/autoload.php system registers auotload using PHP spl_autoload_register which “registers a function with the spl provided __autoload stack. If the stack is not yet activated, it will be.”
1 2 3 4 5 6 7 |
/** * Register SPL autoload function */ static public function register() { spl_autoload_register(array(self::instance(), 'autoload')); } |
Finally, Magento executes autoload method, which loads all class source codes (and again: depending on whether Compilation mode enabled or not it could go different ways).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/** * Load class source code * * @param string $class */ public function autoload($class) { if ($this->_collectClasses) { $this->_arrLoadedClasses[self::$_scope][] = $class; } if ($this->_isIncludePathDefined) { $classFile = COMPILER_INCLUDE_PATH . DIRECTORY_SEPARATOR . $class; } else { $classFile = str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $class))); } $classFile.= '.php'; //echo $classFile;die(); return include $classFile; } |
So now we know that when Mage.php is included in index.php file, the include path set up and the auto loader is registered. After that, we can instantiate Models, Helpers and Blocks using static factory methods on the global Mage class (like Mage::getModel(‘catalog/product’))
As you remember, on the last line of index.php there was a call to Mage.php run() method (below I only put ‘try’ piece of this method without catch part). This is an entry point of front end rendering: request and response setters, initialization of global observers collection, etc.
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 |
/** * Front end main entry point * * @param string $code * @param string $type * @param string|array $options */ public static function run($code = '', $type = 'store', $options = array()) { try { Varien_Profiler::start('mage'); self::setRoot(); if (isset($options['edition'])) { self::$_currentEdition = $options['edition']; } self::$_app = new Mage_Core_Model_App(); if (isset($options['request'])) { self::$_app->setRequest($options['request']); } if (isset($options['response'])) { self::$_app->setResponse($options['response']); } self::$_events = new Varien_Event_Collection(); self::_setIsInstalled($options); self::_setConfigModel($options); self::$_app->run(array( 'scope_code' => $code, 'scope_type' => $type, 'options' => $options, )); Varien_Profiler::stop('mage'); } } |
Next, have a look at Mage_Core_Model_App::run() where most of app initialization work is done, i.e. config loading, request and routing initialization – so this method can be called the heart of application initialization process!
app/code/core/Mage/Core/Model/App.php
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; } |
Partner With Us
Let's discuss how to grow your business. Get a Free Quote.In this method, Magento calls $this->baseInit($options), which in turn loads Mage::getConfig and _init that initializes base system configuration (local.xml and config.xml files) (base configuration provides ability to initialize DB connection and cache backend) by calling loadBase in app/code/core/Mage/Core/Model/Config.php.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
/** * Load base system configuration (config.xml and local.xml files) * * @return Mage_Core_Model_Config */ public function loadBase() { $etcDir = $this->getOptions()->getEtcDir(); $files = glob($etcDir.DS.'*.xml'); $this->loadFile(current($files)); while ($file = next($files)) { $merge = clone $this->_prototype; $merge->loadFile($file); $this->extend($merge); } if (in_array($etcDir.DS.'local.xml', $files)) { $this->_isLocalConfigLoaded = true; } return $this; } |
Ecommerce Development
Take your online store to the next level with BelVG ecommerce development
Visit the pageAfter we loaded local.xml and config.xml files, Magento runs _initModules() of the same class. It, by-turn, initializes active modules configuration and data via Mage_Core_Model_Config::loadModules(). In this loadModules method, Magento loads all active modules from “etc” folders and combines data from the specified xml file names to one object with the help of loadModulesConfiguration().
Then system executes setup scripts via Mage_Core_Model_Resource_Setup::applyAllUpdates() and loads config data from DB via Mage_Core_Model_App::loadDb()
After that, request/store initialization happens
1 2 3 4 5 6 7 8 9 10 |
if ($this->_config->isLocalConfigLoaded()) { $scopeCode = isset($params['scope_code']) ? $params['scope_code'] : ''; $scopeType = isset($params['scope_type']) ? $params['scope_type'] : 'store'; //Init store, group and website collections $this->_initCurrentStore($scopeCode, $scopeType); //Init request object $this->_initRequest(); //Apply database data updates whenever needed Mage_Core_Model_Resource_Setup::applyAllDataUpdates(); } |
And finally we have $this->getFrontController()->dispatch() So routing here is the domain of front controller. We already have the article on front controller pattern by Aleksander Tretjak describing its work in details.
I think that it’s always better to have a look into the source code to understand how things work, but in this case it’d be very helpful to see this request flow on the image. Here is a Magento request flow made by Pavel Novitsky.
Looking for a knowledgeable and reliable Magento custom development provider? Turn to BelVG team!
@Tahir, thank you
Magento request flow diagram link is not working, here is the latest path
http://blog.belvg.com/wp-content/uploads/2012/04/DjZEo.jpg
Nice post for magento developer
Hi Vinod,
Congrats and thank you for your kind words, much appreciated!
Hi Sergei,
Good News..)
I have passed Magento Developer Plus Exam (M70-201) today. Thank you so much for the wonderful articles on Magento exam.
Thanks!!
Vinod