21

What is helper in Magento?

In what cases should one use and not use helpers?

26

Theoretically you should never use helpers.
Helpers are just collections of unrelated methods and are always instantiated as a singletons.
This is basically procedural programming with functions grouped under some namespace (the class name in this case). But since Magento has helpers in the core you can put your methods in there that you have no idea where to put them or if you need to call them in a lot of different places (models, controllers, templates)

Use them as a last resort.

Also Magento requires a helper for each module for translation reasons.
You can just create a helper called Data.php in each module and leave it empty.

  • The only real "use" I've found for helpers is that they're guaranteed to always be a singleton. I've worked on some educational legacy code which was loading collections within foreach loops and all sorts of madness. I found re factoring this terrifying logic to a helper and using it as an object cache to be useful, and left little room for errors from future developers who may have accidentally call getModel instead of getSingleton if I'd placed it in a model. – Luke Rodgers Jul 20 '15 at 10:35
  • @LukeRodgers. I see your point but I don't think that "may have accidentally call getModel instead of getSingleton" qualifies as a real reason to use helpers. I can argue that you can "accidentally" call "delete" instead of "save". What protection you can make to avoid this? I guess "paying attention" is part of software development. – Marius Jul 20 '15 at 10:57
  • Agreed. In these scenarios I guess I'm just trying to code defensively against humanity. – Luke Rodgers Jul 20 '15 at 10:58
  • How would you go about adding custom methods to the core helpers? – tecjam Mar 22 '16 at 17:05
13

The question has two aspects:

  1. Should I write my own helpers and what for?
  2. Should I use the core helpers and what for?

1. Writing helpers

In general, having classes named Helper, Util or similar just says "I have some functions that I don't know where to put" and don't make much sense as a class.

Magento instantiates helpers as singletons and most of the core helpers don't have any state, so the methods could as well be static or even functions without a class. All of this is often considered a code smell, a flaw in the application design.

As Marius already pointed out, you don't need to use helpers for your own code. Just create a default empty helper per module if you use module specific translations, otherwise they won't work. Prefer models (which do not need to extend Mage_Core_Model_Abstract if they don't represent database data) or independent library classes.

However, I would not be too strict about "not using helpers at all" and instead use them for query shortcuts like:

  • access module configuration:

    public function getFooBar() 
    {
        return Mage::getStoreConfig('module/foo/bar');
    }
    
  • factory methods for library classes

    public function getNewFooService()
    {
        return new \Foo\Service(...);
    }
    

You could find other places but IMHO, the module helper is often good enough for things like that.


2. Using helpers

Consuming the core helpers is something you will do quite often.

Examples:

  • __() translation method: To get a translation of a specific module, you should use Mage::helper('module-alias')->__('string to be translated'). This happens implicitly if you use $this->__(...) within a template or block and if you use the translate="..." attribute in XML files
  • Mage::helper('core') methods: localized date, price and currency formating, escaping and encoding data
  • Mage::helper('tax') methods to get information from the tax configuration and calculate prices based on that
  • Mage::helper('catalog/image') provides an interface to create cached and resized catalog images and retrieve their URL
  • Mage::helper('catalog/product_url_rewrite')->joinTableToSelect() joins the URL rewrite table to a product collection query.

There are many more (more or less) useful functions hidden in the core helpers, if you need a specific functionality that is likely to be used in the core somewhere, check if you can reuse a helper method.

Usually these helpers are stateless objects and the methods are query methods (i.e. they have no side effects)

But as always Magento breaks its own unwritten rules and should not be taken as an example. A "good" example how to not use helpers is Mage_Catalog_Helper_Product_Compare which has an $_itemCollection property that can only be initialized once and a $_customerId property that can be changed with a setter. You will find a few more helpers related to the catalog with attached collections. Writing tests for code that uses them or re-use them in different context is not fun, so please don't do that at home.

The catalog/image helper mentioned above is another example of a helper that really should not be a helper. You need to pass a product with init() first which resets its current state, then you set various parameters (like resize(), setQuality()) and in the end you can get the URL with its __toString() method. That looks nice when used in a template but the code is a huge mess and it doesn't make sense as a singleton.


TL;DR:

  • The core helpers contain useful tools.
  • You need helpers for translation
  • Helpers should be stateless
  • In your own modules, avoid using helpers as assorted function collections. In most cases you can find a more appropiate place
  • I've often used helpers in simple ERP integrations based on flat-files. All they do are write and read files from local directories and update other objects (product, order, etc.). They don't have states or corresponding tables of their own in the mentioned instances. What's your take on this? – musicliftsme Jul 21 '15 at 2:33
  • 1
    That violates "no side effects". My usual take on reading and writing files are Reader and Writer models, that actually do have state (at least a file resource). For example, for reading order status data from a CSV file I would have sth. lika a OrderStatusCsvReader model that is used by a OrderStatusUpdater model. This way I also separate the concerns "read data from file" and "update order in Magento" – Fabian Schmengler Jul 21 '15 at 6:21
4

Marius is right. I think helpers are nonsense.

But in magento theory you should put everything into helpers which doesn't change the state of an object, e.g. get formatted price.

But everything you can put into a helper, you can put into a model too. And you can get different instances of a model, which is helpful for testing.

2

I am quite new to Magento, but to me it looks like a Helper is Magento's equivalent of a service: "a set of related software functionalities that can be reused for different purposes". A module exports its offered functionality through services. Use a helper for the functions that you invite other modules to use.

A model should only provide methods that are directly related to getting or setting an object's state, or that are otherwise linked to the instantiated object of the model.

1

Helps are useful to prevent duplicated code (in models, templates, ...) and sometime they are just necessary.

  • for checking if you custom module is enabled, you can place something like Mage::getStoreConfigFlag('my/module/enabled') to every file where you want to check this, or you use Mage::helper('my_module')->isEnabled() with benefits:
    • if ie the config path changes for some reason, you just have to adjust one file
    • you can rewrite helpers isEnabled() method and it will affect all classes that use it, instead of rewriting several files
  • 13th @ How to write a custom extension?: Do not rewrite classes unless is necessary. Use observers and if it's not possible to use helper methods that receive as parameter and instance of a class that you wanted to override. Wrong: Override Mage_Catalog_Model_Product to add the method getProductArticles(). Right. In your helper add getProductArticles(Mage_Catalog_Model_Product $product)
  • make layout updates more flexible using <action method="someMethod"><var helper="module/method" /></action>

You can just create a helper called Data.php in each module and leave it empty.

When using PHPUnit you should add one single line: protected $_moduleName = 'My_Module';

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.