- Magento Front Controller
- Reinstalling Magento Modules
- Clearing the Magento Cache
- Magento’s Class Instantiation Abstraction and Autoload
- Magento Development Environment
- Logging Magento’s Controller Dispatch
- Magento Configuration Lint
- Slides from Magento Developer’s Paradise
- Generated Magento Model Code
- Magento Knowledge Base
- Magento Connect Role Directories
- Magento Base Directories
- PHP Error Handling and Magento Developer Mode
- Magento Compiler Mode
- Magento: Standard OOP Still Applies
- Magento: Debugging with Varien Object
- Generating Google Sitemaps in Magento
- IE9 fix for Magento
- Magento’s Many 404 Pages
- Magento Quickies
- Commerce Bug in Magento CE 1.6
- Welcome to Magento: Pre-Innovate
- Magento’s Global Variable Design Patterns
- Magento 2: Factory Pattern and Class Rewrites
- Magento Block Lifecycle Methods
- Goodnight and Goodluck
- Magento Attribute Migration Generator
- Fixing Magento Flat Collections with Chaos
- Pulse Storm Launcher in Magento Connect
- StackExchange and the Year of the Site Builder
- Scaling Magento at Copious
- Incremental Migration Scripts in Magento
- A Better Magento 404 Page
- Anatomy of the Magento PHP 5.4 Patch
- Validating a Magento Connect Extension
- Magento Cross Area Sessions
- Review of Grokking Magento
- Imagine 2014: Magento 1.9 Infinite Theme Fallback
- Magento Ultimate Module Creator Review
- Magento Imagine 2014: Parent/Child Themes
- Early Magento Session Instantiation is Harmful
- Using Squid for Local Hostnames on iPads
- Magento, Varnish, and Turpentine
As platform, PHP has a long history of relying on the base computer’s underlying file system as a storage mechanism for various application and system functions. This ties in closely with PHP’s practical history of closely modeling the nacent web’s file serving architecture for it’s own.
In an ideal world, as an end-user or application developer using the Magento system, you wouldn’t need to worry about the file system at all. When you’re handling user sessions, you don’t care if they’re stored on disk or in a database, or when you declare a Model class you don’t need to worry about require
ing the source file into the system. That’s because there’s an abstraction that sits on top these systems and allows you to not worry about how they’re implemented.
Unfortunately, we don’t live in an ideal world. There are times when, either out of deadline pressure or lack of an interface, we need to programmatically deal directly with the raw file system in Magento. This article will teach you how to programmatically find the paths of important Magento systems files, which will allow you to build less fragile applications that can withstand system configuration and installation changes.
Finding The Path
If you’re worked much with PHP, you know that finding the full file path to any particular file can be a bit of a black art. When you include
or require
a PHP file, or open a raw file with functions like file
or file_get_contents
using a relative file path, there’s a set of rules that PHP will use to determine which directories need to be searched.
Because this list of directories (called the include_path
is malleable at runtime, if two files with the same name exist in the include path, it’s often hard to tell which one is loaded. Consider the following
include('foo.php');
#files system has
# /lib/foo.php
# /use/web/phplib/foo.php
#which one loads?
Because of this, it’s a common pattern in the PHP to use the magic constants __FILE__
or __DIR__
to find the absolute path to the calling file, and then navigate to the file you want relative to that calling file
$info = file_get_contents(dirname(__FILE__) . '/../data/info.json');
$info = json_decode($info);
This is far from ideal.
First, there’s the problem of symlinks. Depending on your web server system, it’s not always clear if __FILE__
is returning the file’s real path, or its path in the context of a symlink. Because of this, you’ll often see the use of the realpath
function
$info = file_get_contents(realpath(dirname(__FILE__)) . '../data/info.json');
$info = json_decode($info);
While this works, it’s not without its problems. As you can see, this will often lead to code that’s a little hard to read. Additionally, calls to realpath
mean that PHP needs to stat the filesystem to retrieve that information. As traffic to your application grows, these kind of file stats can start to create a performance bottleneck.
Finally, although it solves the problem of ambiguity in PHP’s include path, this isn’t a 100% portable solution. If we move the code from one PHP file (say, a Model in a module) to another PHP file (say, a Magento phtml template), the number of ..
‘s we’ll need is different, since one file is deeper in the hierarchy than the other.
Sometimes __FILE__
is the only way to get where you want to go. Fortunately, Magento offers another option for commonly accessed folders.
Magento Base Directories
Add the following code an empty controller action or other area of Magento where you can run arbitrary code.
$base_path = Mage::getBaseDir('base');
var_dump($base_path);
$etc_path = Mage::getBaseDir('etc');
var_dump($etc_path);
You should see output something like the following
string '/Users/username/Sites/magento1point4.1.dev' (length=43)
string '/Users/username/Sites/magento1point4.1.dev/app/etc' (length=51)
The first folder is the base directory for the entire Magento installation. The second folder is the base directory for Magento’s etc
folder, which holds configuration files.
In the latest Community Edition release of Magento there are 14 different directories that are considered important enough to be retrievable by this method. The static calls to Mage::getBaseDir
are a wrapper/public-api to the getDir
method on a Mage_Core_Model_Config_Options
object. If you take a look at the Magento Model pseudo-constructor in
#File: app/code/core/Mage/Core/Model/Config/Options.php
class Mage_Core_Model_Config_Options extends Varien_Object
{
/* ... */
protected function _construct()
{
$appRoot= Mage::getRoot();
$root = dirname($appRoot);
$this->_data['app_dir'] = $appRoot;
$this->_data['base_dir'] = $root;
$this->_data['code_dir'] = $appRoot.DS.'code';
$this->_data['design_dir'] = $appRoot.DS.'design';
$this->_data['etc_dir'] = $appRoot.DS.'etc';
$this->_data['lib_dir'] = $root.DS.'lib';
$this->_data['locale_dir'] = $appRoot.DS.'locale';
$this->_data['media_dir'] = $root.DS.'media';
$this->_data['skin_dir'] = $root.DS.'skin';
$this->_data['var_dir'] = $this->getVarDir();
$this->_data['tmp_dir'] = $this->_data['var_dir'].DS.'tmp';
$this->_data['cache_dir'] = $this->_data['var_dir'].DS.'cache';
$this->_data['log_dir'] = $this->_data['var_dir'].DS.'log';
$this->_data['session_dir'] = $this->_data['var_dir'].DS.'session';
$this->_data['upload_dir'] = $this->_data['media_dir'].DS.'upload';
$this->_data['export_dir'] = $this->_data['var_dir'].DS.'export';
}
you can see where these directory paths are stored.
Let’s quickly review each one
Mage::getBaseDir(‘base’);
This is your main Magento directory. In a default root level application instal, this is the equivalent of the document root.
Mage::getBaseDir(‘app’);
This is your Magento application directory. This is the directory where the final class Mage...
application file (Mage.php
) is stored.
The default directory (from the Magento base folder) is
/app/
Mage::getBaseDir(‘code’);
This is your Magento code directory. This is base directory for the three Magento code pools (core
, community
, local
).
The default directory (from the Magento base folder) is
/app/code
Mage::getBaseDir(‘design’);
This is your Magento design package directory. This is the base folder that contains the “design packages” for each Area of Magento, (frontend, adminhtml, and install)
The default directory (from the Magento base folder) is
/app/design
Mage::getBaseDir(‘etc’);
The etc
folder is where Magento stores system level (as opposed to module level) configuration files. The name etc
is borrowed from the *nix family of operating systems, and Magento’s configuration files are all XML based.
The default directory (from the Magento base folder) is
/app/etc
Mage::getBaseDir(‘lib’);
Magento’s library
folder is where non-module based Magento code lives. This include a large amount of the system code which allows Magento to run, as well as a number of third party libraries (including the Zend Framework). The library
is also the last code pool Magento will search when attempting to autoload a file.
The default directory (from the Magento base folder) is
/lib
Mage::getBaseDir(‘locale’);
The locale
folder contains the translation files for the core Magento modules. Magento uses a system similar to GNU gettext to provide translated text. Unique strings are stored as key value pairs in the translation files. They “key” is used to lookup which text should actually be displayed. This means for the english locale you’ll see redundant looking strings like
"Add Option","Add Option"
It’s only when you look at the non-english speaking translation files that the system become obvious
The default directory (from the Magento base folder) is
/app/locale
Mage::getBaseDir(‘media’);
Magento’s media folder is where media files (images, movies, etc.) related to data (products) is stored.
The default directory (from the Magento base folder) is
/media
Mage::getBaseDir(‘skin’);
If the word module is the most used yet least well defined programming term, then the words skin and theme are the most abused in the designer’s world. In Magento, the skin
folder contains images, CSS and Javascript files used by your themes.
This is not the only folder where you’ll find images, CSS or javascript though. This folder is meant for files that are customized per theme.
The default directory (from the Magento base folder) is
/skin
Mage::getBaseDir(‘var’);
The var
folder is another one borrowed from the *nix world. The var stands for Variable files, and is intended to store files which are expected to change during normal system operations.
The default directory (from the Magento base folder) is
/var
Mage::getBaseDir(‘tmp’);
The tmp
dir is a temporary directory for safely outputting files into for immediate processing. The operating assumption of the tmp folder is that any developer can write to it and expect their file to stay around for a few minutes, without any expectation that it will be there tomorrow.
The default directory (from the Magento base folder) is
/var/tmp
Mage::getBaseDir(‘cache’);
Magento, rather famously, makes heavy use of caching for activities that might bog down the system if they had to be performed every-time a page loads. For example, Layout XML files are merged once, and then the tree is cached so they don’t need to be merged again. The cache
folder is one place where Magento will store these cached results.
The default directory (from the Magento base folder) is
/var/cache
Mage::getBaseDir(‘log’);
Magento’s log
folder is where is stores the system and exception logs. These logs can be turned on from the Admin Panel’s
System -> Configuration -> Developer -> Log Settings
section. The apache/web-server user will need write permission on this folder and the files therein.
The default directory (from the Magento base folder) is
/var/log
Mage::getBaseDir(‘session’);
During installation you have the option of storing user sessions on disk, or in the database. The session
folder is where the user sessions are written out to and read from if you choose to store them in the filesystem
The default directory (from the Magento base folder) is
/var/session
Mage::getBaseDir(‘upload’);
There are a number of Admin Panel features which allow you to upload media files (default logos, etc.). The upload
folder is where Magento stores these files.
The default directory (from the Magento base folder) is
/media/upload
Mage::getBaseDir(‘export’);
The export
folder is where Magento will write out files meant to be viewed and used by system owners. For example, the Data Flow section of the Admin uses this folder to write out its export files.
The default directory (from the Magento base folder) is
/var/export
Module Base Directories
So, that covers the system folders that Magento gives you access to. There is, however, one other important static method on the Mage
application class class that we should discuss. Give the following a try
var_dump( Mage::getModuleDir('', 'Mage_Core') );
var_dump( Mage::getModuleDir('etc', 'Mage_Core') );
var_dump( Mage::getModuleDir('controllers', 'Mage_Core') );
var_dump( Mage::getModuleDir('sql', 'Mage_Core') );
var_dump( Mage::getModuleDir('locale', 'Mage_Core') );
That static method Mage::getModuleDir
method allows you to retrieve directory path information that’s specific to any module loaded into the system. Like the getBaseDir
method, this call is a public-api to code deeper in the Magento system
#File: app/code/core/Mage/Core/Model/Config.php
class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base
{
/* ... */
public function getModuleDir($type, $moduleName)
{
$codePool = (string)$this->getModuleConfig($moduleName)->codePool;
$dir = $this->getOptions()->getCodeDir().DS.$codePool.DS.uc_words($moduleName, DS);
switch ($type) {
case 'etc':
$dir .= DS.'etc';
break;
case 'controllers':
$dir .= DS.'controllers';
break;
case 'sql':
$dir .= DS.'sql';
break;
case 'locale':
$dir .= DS.'locale';
break;
}
$dir = str_replace('/', DS, $dir);
return $dir;
}
Let’s quickly cover these four folders.
Mage::getModuleDir(‘etc’, ‘Packagename_Modulename’);
Your module’s etc
folder. The etc
folder is a concept borrowed from the *nix, and contains you’re module’s XML configuration files.
Mage::getModuleDir(‘controllers’, ‘Packagename_Modulename’);
Your module’s controllers
folder. Magento’s controllers are not included in the __autoload
implementation. If you ever need to manually include
or require
a controller, use this method to ensure you get the right path.
Mage::getModuleDir(‘sql’, ‘Packagename_Modulename’);
Your module’s sql
folder. The sql
folder contains installer and upgrade files for your Model resources, which are used to install entities and migrate database information during installations.
Mage::getModuleDir(‘locale’, ‘Packagename_Modulename’);
Your module’s locale
folder. The locale
folder contains translation files that are used by Magento when your module is viewed under a different locales.
Wrapup
In this article we explored using the Magento provided methods for retrieving important system file paths. While not necessary, using these methods will help ensure that your Magento solutions and custom modules will be able to weather system updates and help minimize the system administration effort when upgrading the platform.