Whoever worked with Magento probably noticed Magento helpers. Helper is a common element of every module and can be used for different purposes. I will give my thoughts on how Magento helpers should be used and hopefully start a community discussion regarding this topic.
So the first thing that’s important when mentioning helpers in Magento is that they can be used and are meant to be used almost everywhere. It’s easy to get helper instance pretty much anywhere in your application and call its methods. All you need to do is:
Mage::helper('modulename')->someMethod();
For start let’s see what this Mage::helper() method actually does:
app/Mage.php
/** * Retrieve helper object * * @param string $name the helper name * @return Mage_Core_Helper_Abstract */ public static function helper($name) { if (strpos($name, '/') === false) { $name .= '/data'; } $registryKey = '_helper/' . $name; if (!self::registry($registryKey)) { $helperClass = self::getConfig()->getHelperClassName($name); self::register($registryKey, new $helperClass); } return self::registry($registryKey); }
So it basically retrieves helper class from registry or instantiates it and stores it in a registry if it’s not already there. That means you will get the same helper instance in entire application.
Helpers criticism
You would often hear in OOP design discussion that helpers are generally thought of as antipatterns. Here are the the two main reasons for it.
Global scope
Possibility to access variables or methods globally is often considered a code smell. One of the main reasons for this is that with global methods for example it’s harder to have control of where they are used since they can be accessed from anywhere. Debugging is also harder because with this approach it’s not easy to find all the elements that are involved.
SOLID principle violation
According to SOLID principles (the S – Single Responsibility one to be more precise), one class should have only one responsibility. Helpers by definition do not have one responsibility and they don’t deal with only one problem domain. Even in Magento core files you can see that Magento helpers cover wide range of issues. One could also say that by creating helper methods a programmer cannot define where they should actually belong, so they are put in “class for everything”.
Helpers benefits
There are also some good points regarding helpers:
Easy to set up test
It would be very easy to set up a helper unit test. Blocks are dependant on layout and controllers are dependant on http request so you would have to do more work in order to set up test for these. Of course, easiness to test some particular methods depends on what’s called in that method.
Reusable functionality
Good thing about helpers is that you can put some reusable functionality in them. No need to create the same methods across different blocks or rewrite abstract block class.
Good places for methods that don’t really belong anywhere
Usually in a project there is some stuff you can’t really put anywhere else. There are problems that do not have a specific problem domain and do not belong to any specific part of Magento application.
Use cases
Here is some stuff that could be put inside a helper:
Pure functions
Pure function is a function that does not depend on some external state and has no visible side effects (such as changing values of class properties for example). It will always return the same result for same input. Such function can obviously be used in any context since it does not depend on anything externally. Converting centimetres to inches could be an example of pure function. This behaviour guarantees that the method could be called anywhere with no side effects.
Retrieving config values
Storing config path in a class constant and creating a method that would call Mage::getStoreConfig() would be a good idea. Config path probably won’t change over time and wrapping Mage super class method getStoreConfig in a helper method ensures that you won’t have to check the path all the time. Some additional work that needs to be done in order to make these config values usable such as casting for example can also be put in such methods. Here is an example:
app/code/core/Mage/Catalog/Helper/Data.php
class Mage_Catalog_Helper_Data extends Mage_Core_Helper_Abstract { //... const XML_PATH_MSRP_ENABLED = 'sales/msrp/enabled'; //... /** * Check if Minimum Advertised Price is enabled * * @return bool */ public function isMsrpEnabled() { return (bool)Mage::getStoreConfig(self::XML_PATH_MSRP_ENABLED, $this->_storeId); } //... }
Retrieving hardcoded values
Let’s say you need months of the year or some other hardcoded array in a template. It would be better to put that stuff in a helper method than adding additional weight to your template. Same goes for constants.
Usage
There is another topic I would like to cover in this article. Sometimes it’s not so clear whether some functionality should be put in block or helper. Same goes for model or helper situation.
Helpers and blocks
I would say that it’s easier to make a choice in a block vs helper situation. If some functionality is meant to be used in a lot of different places throughout the application, put it in a helper. If it’s meant to be called in a specific template and you don’t think it’s reusable put it in a block.
Helpers and models
With models it’s a bit different, since both models and helpers can be called from anywhere in Magento. Models have a very specific problem domain. They usually represent an entity but they can be in charge of other tasks such as cron jobs or event observing. Helpers on the other hand have a loosely defined problem domain so for example in catalog helper you can find anything that is in some way related to catalog so it’s a lot less specific. Therefore if you notice that you are doing too much in helper you should consider creating a specific model for that functionality instead. Another difference is that models are meant to hold a certain state (loaded, non-loaded for example), where in helpers you should avoid holding a state. That’s why if you need class properties you should probably move your methods to model. Helpers are more like some single functionalities grouped so it doesn’t make sense to keep a property that would probably be totally unrelated to the helper class itself. One tradeoff Magento core team made is keeping instances of objects in class properties in order to prevent querying the database and instantiating classes more times than needed. I think it’s an architecture sacrifice that’s acceptable.
Wrap up
Helpers can definitely be very useful if used wisely. These are only my thoughts that are coming from my experience. You are welcome to share your opinion on helper usage.
Would you like to recommend this article to your friends or colleagues?
Feel free to share.
Article "How to use Magento helpers" has 5 responses
First, Thank you for contributing to Magento community with one more excellent article. Well wrote!
Just want to try to defend Helpers from criticisms, I’m always on the side of weaker :)
Possibility to access variables or methods globally is often considered a code smell.
It’s true. But, in theory, Helpers should not contain state (variables), only functions and constants. So if you find variables in Helper, it’s because of Developer’s mistake and Helper’s misuse, not because of Helpers.
Helpers by definition do not have one responsibility and they don’t deal with only one problem domain.
Helpers are not intended to have one responsibility, there are just what their name says – helpers. Helper classes are just unlucky way to collect them all in one place, so they can be easily found and instantiated. I’ll rather say that it was misuse of classes, but I don’t see better way to accomplish that.
Thanks Sinisa for your comment.
Regarding your first point, I think that the fact that something contains state does not have anything to do with that being accessed globally or not. I was just criticizing possibility to access globally in theoretical sense.
I think we agree on your second point. I was just theoretically speaking about SOLID principles violation.
Thank you for sharing,
I totally agree with your vision about Helpers.
My 2 cents regarding the SOLID principles; SOLID principles represent an asymptote which we tend towards and not an objective we can always accomplish, especially when we have to deal with technical debt (aka code written by others, like Magento framework).
All we can do is doing our best to tend as close as possible to the asymptote according to expected best practices.
Kind regards,
Alessandro
Thanks Alessandro, really well said.
This is one of the most valuable articles about Magento development practice. Great guideline for proper usage of a helper pattern and very good explanation of SOLID principles.