CTO, Software Engineer, Indie Hacker, Gamer
Magento has a system that allows a developer to easily override a core class by introducing a rewrite into the module’s XML configuration. This works by utilising a string as an abstraction of the true class name, passed to the
Mage::getModel($key) method for class instantiation, instead of the traditional
$object = new MyClassName();.
It follows that we can then easily generate a lookup table mapping keys to class names, and return the corresponding class. This lookup table is populated and modified by the Magento initial configuration and rewrites.
This is great right? If I want to add some extra functionality to the
getProduct() method of the
Mage_Product_Model_Product class then I just create my own
Nick_Rocks_Model_Product class and change the functionality, and add a rewrite.
Now what happens when I need some extra-extra functionality added to the
getProduct() method? I decide I don’t have enough time to rewrite the module myself, so I check out Magento Connect and find a module that’s a perfect fit for my current requirements. I install, only the find that the extra functionality added by my initial module has been removed and only the extra-extra functionality remains. Dammit. Bad ju-ju.
The F-ugly How can we get around this problem? We have two situations.
In the first situation we can quite easily get around our problem by implementing multiple inheritance, of sorts. An implementation is offered by Josh Ribakoff. There is an obvious performance overhead introduced here – what if we have a long ass list of classes that are attempting to rewrite this class? We have to invoke every one of these classes and check the object for the existence of the method, or use some très clever reflection. Bad ju-ju.
The previous solution does not solve the problem of overriding specific methods. Consider our long ass list of classes all wanting to override the same method? Which one do we let do it?
It’s simple. Use event-listeners, helpers, or extend (not override) the core classes to form your own.
The only drawn back to performing these kinds of changes is that they may require a design change when overriding a core class would not. Big deal? Anyone serious about their store will hire someone to install the module and make the design changes themselves. There should be no cutting corners when confidential user information is involved.
Okay, so it’s not so simple. Sometimes the hooks for observing simply do not exist in the code. Some of this is down to the core Magento developers. I’m sure they’d agree that they don’t always code with a module developer in mind. Take the mass action section of the order screen for example. The only way to add another option to the dropdown there is to extend the class and modify the button yourself.
Here are some ideas.
When to (ideally) use event-listeners:
When to use helpers:
Mage::helper('rewards')->getOrderRewardPoints($_order), instead of
When to extend the core classes:
As Magento continues to grow we need loosely couple our modules to the internal workings of Magento. Honestly, a module should be able to run without extending a single core class, even if it needs some changes to the design.
I think this is the way to do it. What do you think?