Let’s pretend your Magento store needs to modify core functionality offered inside of the app/code/core/ folder. I’d have to smack you if you went modifying those files directly as it wrecks your ability to easily maintain changes throughout upgrades. Fortunately, Varien was good enough to know that the way they developed Magento isn’t the way everyone may need it to work. Barely on the surface, you have three code folders: community, core and local. In this post, I’ll be reviewing how to rewrite and extend those classes inside of the core folder.
Extending Core Classes
As mentioned in my Multi-Store and Internationalization post, PRPL adopted an inverse Translate method that fetches from translate.csv files before those located in app/locale/. In order to do so, we needed to make this change global while keeping the scope of impact as minimal as possible.
Magento manages their dependency injection through the XML configuration files. When you want to rewrite a class, you can tell Magento to look elsewhere from where it normally would.
Inside of app/code/local/, we have a namespaced folder called Prpl, which is where we’ll be putting any of our custom code1. Place the following code inside of app/code/local/Prpl/Core/etc/config.xml:
<?xml version="1.0"?>
<config>
<modules>
<Prpl_Core>
<version>0.1.0</version>
</Prpl_Core>
</modules>
<global>
<models>
<core>
<rewrite>
<translate>Prpl_Core_Model_Translate</translate>
</rewrite>
</core>
</models>
</global>
</config>
It should be pretty obvious what’s going on here: We’re telling Magento to rewrite the “core/translate” model to our class. The cool part about overriding Magento classes in this way is that we can extend them2. Now to create the class, Prpl_Core_Model_Translate, with the following contents:
class Prpl_Core_Model_Translate extends Mage_Core_Model_Translate
{
/**
* Reverses the priority of translations to check translate.csv first, and
* then the locale packages second -- the way it should be.
*
* @param text $text
* @param text $code
* @return text
*/
protected function _getTranslatedString($text, $code)
{
$translated = '';
if (array_key_exists($text, $this->getData())) {
$translated = $this->_data[$text];
} elseif (array_key_exists($code, $this->getData())) {
$translated = $this->_data[$code];
} else {
$translated = $text;
}
return $translated;
}
}
Enabling Your Namespace
Lastly, lets not forget to enable your new module. We prefer using a module xml file called Prpl_All.xml, which is placed at app/etc/modules/. The basic contents would look like this:
<?xml version="1.0"?>
<config>
<modules>
<Prpl_Core>
<active>true</active>
<codePool>local</codePool>
<depends>
<Mage_Core />
</depends>
</Prpl_Core>
</modules>
</config>
After that, you should be all wrapped up and ready to go. If caching is enabled, you’ll likely have to clean it out.
Magentoisms
Today I was working on a new module for one of our clients for some enhanced inter-product support functionality. Since it’s largely focused towards live search functionality, I figured I would piggyback some of the CatalogSearch functionality to reduce duplicate code.
In doing so, I ran into a small roadblock in that it appears overwriting controllers isn’t as auto-awesome in Magento as with models and other classes. I didn’t investigate far into the “why”, but the Magento autoloader wasn’t playing nicely.
The point I’m making with this is that little things like this are bound to crop up and they’re hurdles you simply have to expect. Keep special attention on the XML files: they have been known to be sensitive to whitespace. When this happens, Magento doesn’t give you any considerably useful errors. *face palm*
Foot Notes
- 1 If you’re creating a namespace for your company to be placed in multiple client projects, I would recommend plopping it in the community folder. I prefer having the ability to have a common code base that we can then extend further in local for the client if necessary.
- 2 The other method of rewriting Magento classes, which I don’t recommend, is to copy the entire contents of the class you want to overwrite into the local folder and put it inside of a mirror file (e.g. Mage/Core/Model/Translate.php). Doing it this way totally blows for two primary reasons: 1) you need to maintain more code and 2) if Varien updates Magento, see point 1. This is the method I used prior to discovering XML rewrites… those were dark, dark days. It’s a total pain in the ass and wreaks of code smell. I can’t think of any particularly enticing reasons to use this approach.