Magento Advanced Episode 1 – Index.php … the beginning!

20 juin 2014

In the first series of tutorials I showed you how to develop a module on magento, you are now likely to know and build a module to know the minimum to develop Magento.

Now it is time to go further in the operation of this wonderful e-commerce platform.

This tutorial is the first in a long series .. I suggest you start with the first series on magento module development. Even if it’s not mandatory, it will help to follow these tutorials more easily.

When you start your browser, you type an address that points to the directory on your server (where magento is installed) and all requests will be redirected to the index.php of the root directory.

Let us look at this file in detail, my explanation in the comments

How the index.php works ?


/*
 * We are testing the php installed version and we raised an error if she is less than PHP 5.2.0
 */
if (version_compare(phpversion(), '5.2.0', '<')===true) {    echo  '</pre>
<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>
Magento supports PHP 5.2.0 or newer. <a href="http://www.magentocommerce.com/install" target="">Find out</a>
how to install Magento using PHP-CGI as a work-around.</div>
<pre>';
    exit;
}
/**
 * Error reporting – set the error level reporting in php
 */
error_reporting(E_ALL | E_STRICT);
/**
 * we include the file includes/config.php, it's used to make the compiled version of magento worked
 */
$compilerConfig = 'includes/config.php';
if (file_exists($compilerConfig)) {
    include $compilerConfig;
}
/*
 * We are looking if we should go to the downloader or not
 */
$mageFilename = 'app/Mage.php';
$maintenanceFile = 'maintenance.flag';
if (!file_exists($mageFilename)) {
    if (is_dir('downloader')) {
        header("Location: downloader");
    } else {
        echo $mageFilename." was not found";
    }
    exit;
}
/*
 * we are looking if the flag maintenance.flag is at the root of the magento directory
 * if he is here, we show a 503 error.
 */
if (file_exists($maintenanceFile)) {
    include_once dirname(__FILE__) . '/errors/503.php';
    exit;
}
/*
 * We now include app/Mage.php
 */
require_once $mageFilename;
/*
 * Here we are setting if we should use the profiler or
 * not and if we lunch the website with the developper's mode
 * These two lines are very usefull for the debug
 */
#Varien_Profiler::enable();
if (isset($_SERVER['MAGE_IS_DEVELOPER_MODE'])) {
    Mage::setIsDeveloperMode(true);
}
#ini_set('display_errors', 1);
/*
 * We let the permission script to 0.
 */
umask(0);
/*
 * Here is very important, we are looking the server values MAGE_RUN_CODE
 * and MAGE_RUN_TYPE, It will be use to define wich store magento will use.
 */
/* 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';
/*
 * we are calling for the run() method of the Mage class, wich is included
 * in the file /app/Mage.php (wich has been included just few lines before)
 */
Mage::run($mageRunCode, $mageRunType);

How can magento retreive his files ?

When included the Mage.php, this is not just a simple class inclusion. Indeed, before the class declaration we can find some instructions:

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 "Mage_Core_functions.php";
    include_once "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();

These instructions in particular define the include path (which defines a list of directories where the require(), include(), fopen(), etc … will fetch the files). You can see that it’s here where magento declares the codePool (app/code/local app/code/community, app/code/core) and where it declare the library directory ( /lib ).

Then we included Varien/autoload.php and Mage/Core/functions.php

With the include path said before, it will fetch the file Autoload in:
/app/code/local/Varien/autoload.php

but will not find it, so it will go in:
/app/code/community/Varien/autoload.php

but did not find it either, so it will go in:
/app/code/core/Varien/autoload.php

but did not find it either, it will finally look in:

/Lib/Varien/autoload.php

And he will finaly find the file and include_once.

The class Varien_Autoload is what allows magento to make the links between the file name and path relative to inlude path. So my class Roger_Toto give the path /Roger/toto.php Magento will therefore look at the file in the following order (and stop at the first file found):
app/code/local/Roger/toto.php
app/code/community/Roger/toto.php
app/code/core/Roger/toto.php
lib/Roger/toto.php

In short, you now understand how Magento retreive its file from the names of its classes and you now know where this process is performed. Anyway … Let us return to our sheep! We arrive at index.php which included app/Mage.php and starts the run() method. Here what interests us ! We included app/Mage.php file called run() method. This method is as follows (my explanations are still in the comments):

/**
    * 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');
    //we defined the absolute path
           self::setRoot();
    //instanciate the application
           self::$_app    = new Mage_Core_Model_App();
    //instanciate  the events collection.
           self::$_events = new Varien_Event_Collection();
     //instanciate the configuration model
           self::$_config = new Mage_Core_Model_Config($options);
     //lunching the run method of the application
           self::$_app->run(array(
               'scope_code' => $code,
               'scope_type' => $type,
               'options'    => $options,
           ));
      //we are doing the necessary things in case of exception
           Varien_Profiler::stop('mage');
       } catch (Mage_Core_Model_Session_Exception $e) {
           header('Location: ' . self::getBaseUrl());
           die();
       } catch (Mage_Core_Model_Store_Exception $e) {
           require_once(self::getBaseDir() . DS . 'errors' . DS . '404.php');
           die();
       } catch (Exception $e) {
           if (self::isInstalled() || self::$_isDownloader) {
               self::printException($e);
               exit();
           }
           try {
               self::dispatchEvent('mage_run_exception', array('exception' => $e));
               if (!headers_sent()) {
                   header('Location:' . self::getUrl('install'));
               } else {
                   self::printException($e);
               }
           } catch (Exception $ne) {
               self::printException($ne, $e->getMessage());
           }
       }
   }

The most important (the what is important to learn) on these file is that lines :

 //we defined the absolute path
       self::setRoot();
 //instanciate the application
       self::$_app    = new Mage_Core_Model_App();
 //instanciate  the events collection.
       self::$_events = new Varien_Event_Collection();
 //instanciate the configuration model
       self::$_config = new Mage_Core_Model_Config($options);
 //lunching the run method of the application
       self::$_app->run(array(
               'scope_code' => $code,
               'scope_type' => $type,
               'options'    => $options,
        ));

This is where we will launch the application (Mage_Core_Model_App) ie do much MUCH actions include:
– Partner config files to the application
– Verify if we can find an answer in the caching system and send it back
– Initialize all modules (apply the updates, load informations in the database)
– Define which store we will use
– Recover frontController which returns the response to the visitor’s browser.

Use classes outside magento Magento?

Sometimes we just want to test something like if the function we just created in our helper works properly.
For this, we will do the same job as Magento but we will do the minimum necessary for the application to work correctly.
Ie:
– Include app / Mage.php
– Set the default permissions of our script
– Launch Application

We will therefore create a test.php file to the root of our magento.
If you want to put it outside, do not forget to change the path for the require_once of the Mage.php file.

//Include app/Mage.php
require_once 'app/Mage.php';
//Defining default permission of the script
umask(0);
//Lunch the application
Mage::app();
/** Now HERE i can do whatever i want like calling a Mage::getModel('...') for exemple */

As you can see here we use the method Mage::app() but the default file index use Mage::run(). The difference is that Mage::app() is lighter.
Indeed, Mage::run() will use $app->run() to start the application while Mage::app() will only use $app->init() to initialize the application . The big difference between these two is that treatment of Mage::run() will manage the « request flow » and « output » so it will launch all the mechanism to retrieve the controller, the method etc … and will handle what the script will return to the browser via the layout and templates.

In our example we do not want to use the layout and templates, we just want to instantiate objects through our factory, Mage::getModel(‘…’), so we using Mage::run() is not necessary.

In Short when you want to use the magento classes in a separate file … you use Mage::app because it is lighter … if you need to remember one thing about the difference between Mage::app() and Mage::run() just remember that.

Here it is already the end of this tutorial, if you like this tutorial leave me a message below, do not hesitate to ask in the comments I’ll try to answer. Help me by sharing this article with your friends on twitter & follow the facebook page please :)

In the previous tutorial series, i had a lot of visits but very few people share my articles yet :( a tweet takes just one click guys, it’s nothing for you but for me it is a very big thing, i really enjoy each tweet. Anyway, here it is really the end of the article ..

Stay tuned for the next which will cover a very important concept for us…magento developers :)

You should read this too :
  • No Related Post
Hashid Hameed # 25 juin, 2014

great to see you back! always been a big fan of ur tutorials!

Vous aussi donnez votre avis
(requis)



Expert magento sur Lille - Pierre FAY