Frustrated by Magento? Then you’ll love Commerce Bug, the must have debugging extension for anyone using Magento. Whether you’re just starting out or you’re a seasoned pro, Commerce Bug will save you and your team hours everyday. Grab a copy and start working with Magento instead of against it.

Updated for Magento 2! No Frills Magento Layout is the only Magento
front end book you'll ever need. Get your copy
today!

If you’ve spent any time with Magento, you know the importance the “global config” plays in a the system. However, you may not fully understand how that configuration tree is built. Usually, most tutorial authors (myself included), will gloss over this and say something like

All the module’s etc/config.xml files are merged into one

While this statement is true, it’s only part of the story. Understanding what’s in this tree, and how it’s loaded, is a necessary step on the road to Magento mastery. There’s more than just module configuration in the Magento global config. Over the next few articles we’ll cover exactly what’s in the configuration tree, and where it comes from.

The specifics of this article refer to Magento 1.6.1 CE, but the principles discussed apply to all versions.

Magento calls this static method at the bottom of the index.php bootstrap file. The code in the run method is responsible for executing a full Magento HTTP request. If you remove the profiling lines, that means Magento is only 5 lines of code! Who says it’s complicated?

This is where the Magento global config is instantiated, and this is the object that will be used to load and interact with Magento’s XML configuration files. For those new to Magento, the Layout XML files are a separate system, covered in my No Frills Magento Layout book. Layout XML files are not strictly configuration files. Instead, Layout XML files form the basis for a domain specific programming language which allows users to interact with the Layout and Block objects. Because of this, they don’t fall under the domain of Mage_Core_Model_Config, and will not be covered in this series.

which is a general class for dealing with XML configuration files. These classes exist to create a structure and “configuration context” around PHP’s generic XML objects. By ensuring Magento client developers always ask for configuration information via the Config object, Magento system developers can provide those client developers with shared functionality, and also allow them to take advantage of functionality like caching without having to change their code.

Note: Client here doesn’t refer to “client side browser development”. Instead, client developer means someone using Magento to create a store or application. These people are clients of the of the Magento system. The line between client and service developer is often blurred in Magento, but it’s still a useful metaphor for understanding the intent of core code.

Loading the Config

That’s the config object instantiated, but so far we haven’t loaded any XML files. What gives? If you take a look at the class’s constructor

we see some code, but at first glance the code doesn’t look like it loads any XML. That glance would be correct, but we’ll come back to this constructor code it a bit, so keep it in the back of your mind.

To find the point in the application startup process where an XML tree is loaded, we need to follow the application startup execution chain a few methods down the stack. We’ll be breezing past some things that are worth exploring, but don’t relate directly to configuration loading.

We’ll start with the app model object’s run method, which is called by the Mage class’s run method

This gives the app model object easy access to the config. Remember, in PHP 5+ objects are references. This means both the Mage class and the core/app object have a reference to the same config object. When one changes, they both change.

will “glob up” any XML files in the app/etc folder. In a standard base system, the value returned by a call to $this->getOptions()->getEtcDir(); is /path/to/magento/app/etc. In a normally operating system the $files variable will contain the following two strings.

This code takes the first filename in that array, and passes it to the loadFile method. Unless you’ve been using PHP for a very long time, you may not be familiar with the current method. Time was, PHP didn’t have a handy foreach loop. In versions prior to PHP 4, the only way to loop over an array was to use a for($i=0;$i<count($array);$i++) style construct or use PHP’s internal array functions (current, next, etc. to manipulate an arrays internal “pointer”.

Why this construct is being used here is unclear. Perhaps there’s a performance gain, or maybe the core developer was new enough to PHP that they didn’t know about the newer constructs and current was encountered before array_shift. Regardless, all you need to know is the first item of the array, (/path/to/magento/app/etc/config.xml), is being passed to the loadFile method. This method is located on the base Varien_Simplexml_Config class.

The classes which inherit from Varien_Simplexml_Config may implement their own processFileData method to manipulate the XML string before loading it. The Mage_Core_Model_Config class doesn’t take advantage of this for anything, but it’s worth noting, as you never know what another developer may have done with a class rewrite.

we can see that loadString is responsible for creating a SimpleXML object from the passed in string, and assigning that object to the internal $this->_xml property after ensuring its an instance of Varien_Simplexml_Element.

Wait, what? Where does Varien_Simplexml_Element come from? Shouldn’t a simple XML object be an instance of SimpleXMLElement? Turns out there’s a little known/used feature of the simple xml loading functions that allows you to specify a custom class for your SimpleXMLElement objects. This allows you to create custom methods that are available directly on any simple XML objets you create. That’s because the objects are no longer SimpleXMLElements, they’re now objects that are instances of your class.

If you take a look at the definition of Varien_Simplexml_Element, you can see it inherits from SimpleXMLElement, and adds multiple convenience methods for dealing with XML objects.

you can see we’re specifying the class to use (the second function parameter) with the $this->_elementClass property. You’ll may also remember this property was passed in as a second parameter of the loadString method.

This means any simple xml object created will be a Mage_Core_Model_Config_Element, which has Varien_Simplexml_Element as an ancestor.

Class Hierarchy Review

Before we continue, we’ve just introduced a number of new classes, and it may be useful to review the hierarchy and what they’re used for.

The Mage_Core_Model_Config class, which extends Mage_Core_Model_Config_Base, which in turn extends Varien_Simplexml_Config will be the class for our Magento global configuration object. Although there’s nothing enforcing this in the system, this object should be thought of as a global and/or singleton object. Many different Magento objects may have a reference to this configuration object, but each of these references should be pointing at the same object.

The Mage_Core_Model_Config object has an _xml property. This property will store a PHP SimpleXML object which represents the tree for the Magento global config. However, this SimpleXML object is instantiated with a custom PHP class. This class is Mage_Core_Model_Config_Element, which extends a Varien_Simplexml_Element, which extends the built in SimpleXMLElement.

This hierarchy of classes may seem overly complicated, and while I’d personally agree, a key piece of the core team’s original design goals for Magento was to make the system as flexible and customizable as possible, and to push the limits of PHP 5’s often under-utilized object oriented features. It’s easy see a situation where one member of the core team though “Hey, let’s use the custom class feature of the simple xml objects”, and another member of the core team though “Configuration XML should have wrapper classes which share the same base”.

If you’re this far along you probably don’t need reminding, but it’s often necessary to put aside how you would have implemented an online retail system and accept how Magento’s been built.

At this point, we’re about the enter the while loop. Our _xml property contain the XML tree for the file at app/etc/config.xml. This is the absolute minimum configuration Magento needs to bootstrap a basic system. The while loop will go through the remaining XML files and load each one. If you’ve ever accidentally copied another XML file into the app/etc folder and had weird things happen, this is the reason for that weirdness. Magento will load ANY file that ends in .xml.

The loading of these files gets a little tricky. Let’s take a look at the code responsible for this. First, Magento clones the object in $this->_prototype.

Mage_Core_Model_Config_Base is the same class that Mage_Core_Model_Config has as an ancestor. When Magento clones this object into the variable $merge, it’s making a copy, and then loading the current XML file into the new object

but as the configuration system was likely one of the first parts of Magento built, it seems like they were still working out what sorts of abstractions they’d be using, which partially explains this sort-of prototypical inheritance pattern for the configuration objects.

That aside, we’re finally at the really tricky part. We now have two XML config objects. There’s our Magento global config object, and this new config object. Each config object contains an individual XML tree. The question we’re now faced with is

How do we combine these two trees into a single object

The new object’s contents are merged with the first tree via the extend method.

you can see the ultimate extend method is implemented on the custom simple XML object class, Varien_Simplexml_Element. This is also the first time we’ve encountered the getNode method. When used without a parameter, getNode returns the contents of the $this->_xml property.

Extending a Varien XML Node

So what does is mean to “extend” or “merge” two XML trees in Magento? Rather than walk through the code, we’re going to describe how extend works. It’s a method that will recursively copy one xml tree into the first, (recursively!). That is, we’re extending the original XML tree with the second.

The basic metaphor is our current XML tree lacks certain nodes, so its asking the new XML tree to provide them.

That said, this “second tree wins” behavior may be avoided by using the extend method’s second $overwrite parameter

$first->extend($second, false);

When you pass this parameter in as false, you’re instructing Magento NOT to overwrite nodes in the first tree. Only new nodes from the second tree will be added, conflicts will be ignored. This means the values in the second tree are preserved.

The code that does this is worth exploring, especially if you’re interested in recursion. However, it’s beyond the scope of this series to explore that deeply.

One last note before we move on. You’ll notice that, in the extend method mentioned above on the base config class, the $overwrite property defaults to true. However, this call wraps to anotherextend method, defined on our custom simple xml class

which has a prototype that defines the default as false. So remember, if you’re working with the config objects, extend will default to overwriting nodes but if you’re working with the raw Varien_Simplexml_Element nodes, the default behavior is to skip merging nodes that conflict. If you’re going to be doing a lot of work directly with both these objects, it’s probably best to be explicit with your override parameter and not rely on the defaults.

The local.xml file is created when you go through the installation steps after running Magento for the first time. By marking this flag as true, the core code has given Magento client developers the ability to programmatically determine if this is an “installed” system, or if it’s a system that still needs its local.xml file created.

At this point, we’ve now loaded our base Magento configuration.

Wrap Up

So that’s the first part in our series on the Magento global config. So far we’ve covered loading the base configuration tree, as well as the general mechanism Magento uses to merge multiple XML configuration trees. Although we’re several thousand words in, we’ve only scratched the surface. Next time we’ll be covering the where and how of Magento’s module configuration files, and what effect this loading has on our global configuration object.