Magento makes use of PHP 5’s autoloading feature to include classes. One of the more irritating aspects of a large application is including class files at the top of each script every time you create a new class. Autoloading eliminates this problem. This article represents how Magento uses its Varien_Autoload
class.
Firstly, Magento sets its include paths to be in four different directories. This can be seen within the Mage.php
class.
/** * Set include path */ $paths = array(); $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'));
So we have /app/code/local
, /app/code/community
, /app/code/core
and /lib
directories.
Note that the constants BP
and DS
are defined near the top of the Mage.php
file. BP
is the base path (i.e. your Magento root directory) and DS
is the directory separator.
It’s also worth noting the order of which the paths are included. If you’re familiar with class overrides in Magento, you’ll know that common practice is to use the local
code pool. The reason for this is because of the code above.
Included files are looked for firstly in the local
directory, followed by community
and so on.
A bit further down the Mage.php
file, we come across an include to the Varien_Autoload
class.
include_once "Varien/Autoload.php";
And just below this inclusion, we come a register()
method of Varien_Autoload
.
Varien_Autoload::register();
If we head to this class, the register()
method contains the in built spl_autoload_register()
function as we can see below.
/** * Register SPL autoload function */ static public function register() { spl_autoload_register(array(self::instance(), 'autoload')); }
So the first parameter of the spl_autoload_register()
function is a value returned from the static instance()
method, which is a new instance of the Varien_Autoload
class.
/** * Singleton pattern implementation * * @return Varien_Autoload */ static public function instance() { if (!self::$_instance) { self::$_instance = new Varien_Autoload(); } return self::$_instance; }
The magic __construct()
method is then called that delegates to the registerScope()
method passing in the $_scope
property which is set to default
, found near the top of the Varien_Autoload
class.
/** * Class constructor */ public function __construct() { register_shutdown_function(array($this, 'destroy')); $this->_isIncludePathDefined = defined('COMPILER_INCLUDE_PATH'); if (defined('COMPILER_COLLECT_PATH')) { $this->_collectClasses = true; $this->_collectPath = COMPILER_COLLECT_PATH; } self::registerScope(self::$_scope); }
The registerScope()
method checks if the compiler include path constant has been defined and if it has, we include the php class files within this path.
static public function registerScope($code) { self::$_scope = $code; if (defined('COMPILER_INCLUDE_PATH')) { @include COMPILER_INCLUDE_PATH . DIRECTORY_SEPARATOR . self::SCOPE_FILE_PREFIX.$code.'.php'; } }
So returning back to the register()
method, let’s focus on the second paramater which is autoload
. This parameter is the registered function.
/** * 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; }
The important part here is to take note if how Magento converts the included path classes to class names. If we ignore the compiler include path check for now, we can see the line below.
$classFile = str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $class)));
If you uncomment the echo $classFile;die();
line within this method, you can see that it outputs Varien/Profiler
. The Varien_Profiler
class is the first class to get autoloaded using this method.
So the string conversions that take are as follows.
The $class
variable that gets passed in the autoload()
method contains in this example, Varien_Profiler
. This gets converted to Varien Profiler
via the inner str_replace()
function.
ucwords(str_replace('_', ' ', $class))
Varien Profiler
then becomes Varien/Profiler
via the outer str_replace()
function.
str_replace(' ', DIRECTORY_SEPARATOR, ucwords(str_replace('_', ' ', $class)));
At the end of the autoload()
method, we then append a .php
extensions onto the end of the class file and the class file gets included and returned.
$classFile.= '.php'; //echo $classFile;die(); return include $classFile;
If we couple this with one of our included paths that we saw in Mage.php
, we can see that a full path of lib/Varien/Autoload.php
is established.
If you enable and run compilation within System -> Tools -> Compilation
, by checking the includes/src
folder from the Magento root directory, you will get an idea of the class files that are loaded in the autoloading process.
Note: This article is based on Magento Community/Open Source version 1.9.