27

The latest builds of Magento 2 have done away with the Mage class. This mean we've lost the Mage::helper method.

Is there a replacement technique (helper factory?) for instantiating helpers in Magento 2? Or are we expected to use the new Object manager class, and just instantiate the helper as a singleton/cached object with get (vs. create)

5 Answers 5

33

I see you came to right solution, just want to summarize.

Constructor injection should be used to retrieve helper (or any other instance) in whatever class you need:

class SomeClass
{
    public function __construct(\Magento\Core\Helper\Data $helper)
    {
        $this->helper = $helper;
    }

    public function doSmth()
    {
        $this->helper->someMethod();
    }
}

Notice that no phpDoc comments are required, Magento will read constructor signature directly to figure out what dependencies are required.

\Magento\Core\Helper\Factory should be used only in those rare cases when you have to call a lot of multiple helpers, or you don't know exactly which one you need.

Usage of Object Manager directly is strictly discouraged. So please avoid using:

\Magento\Core\Model\ObjectManager::getInstance()

It's there only for serialization/deserialization.

3
  • do not use static as it can't be tested with PHP unit and yes it is discouraged. All M2 dependencies are done through the constructor, and managed by the Object Manager internally, and will retrieve it as Singleton Also do not use _ to indicate a property visibility, All M2 naming should use the camecase
    – PartySoft
    Commented Jul 17, 2015 at 15:03
  • @Anton Kril if we use helper in template, like $this->helper('Magento\Catalog\Helper\Image'), it follows the best practice? Commented Apr 24, 2016 at 10:09
  • 2
    No, it does not. Templates should only reference blocks. Helpers should be avoided
    – Anton Kril
    Commented Apr 25, 2016 at 12:31
10

It looks like Magento's encouraging folks to use their new automatic dependency injection system to get helpers and models into objects via the object's constructor.

The short version? If you have an object that's instantiated by the object manager, and decorate a constructor with a PHPDoc @param, and the parameters has a proper type hint set, the object manager will automatically instantiate the helper (or, I believe, other objects) for you.

For example, the following constructor would inject a a core data helper into the object.

/**
* @param \Magento\Core\Helper\Data $coreData
*/        
public function __construct(\Magento\Core\Helper\Data $coreData)
{
    $this->_coreHelper = $coreData;            
}
8
  • This is the correct answer - great sleuthing; was not totally obvious to me even after a lot of digging.
    – philwinkle
    Commented Nov 8, 2013 at 17:54
  • 2
    OK ...now my head hurts...a lot. You mean that we are supposed to use PHPDoc to "write" code? This is madness. I quit.
    – Marius
    Commented Nov 8, 2013 at 19:15
  • @Marius hahaha this is not that uncommon - Alan's blog explains it to some extent.
    – philwinkle
    Commented Nov 8, 2013 at 21:10
  • 3
    @philwinkle. I've read his article. Very interesting, but I still say this is madness. Call me old fashioned, but "back in my days" code was code and comments were those things that almost nobody bothered to write.
    – Marius
    Commented Nov 8, 2013 at 21:28
  • Oh...and by the way. +1. Good question & nice answer.
    – Marius
    Commented Nov 8, 2013 at 21:29
9

Apart from all above answers, if you have to use helper in phtml template you can simply do like this:

$this->helper('[Vendor]\[Module]\Helper\[Helper Name]');

I hope it is helpful if somebody didn't know it before ;)

6

The way that helpers are instantiated (at least for the new Backend (~dev50) module) are via a helperFactory:

/**
 * Return helper object
 *
 * @param string $name
 * @return \Magento\Core\Helper\AbstractHelper
 */
public function helper($name)
{
    return $this->_helperFactory->get($name);
}

Which is essentially just a specialized type of a model factory. E.g: Magento\Core\Block\Context line 143 (dev50) as part of the constructor:

\Magento\Core\Model\Factory\Helper $helperFactory

The helper factory will return the requested model based on the class name and ensure that it is an instanceof the helper abstract class:

/**
 * Get helper singleton
 *
 * @param string $className
 * @param array $arguments
 * @return \Magento\Core\Helper\AbstractHelper
 * @throws \LogicException
 */
public function get($className, array $arguments = array())
{
    $className = str_replace('_', '\\', $className);
    /* Default helper class for a module */
    if (strpos($className, '\Helper\\') === false) {
        $className .= '\Helper\Data';
    }

    $helper = $this->_objectManager->get($className, $arguments);

    if (false === ($helper instanceof \Magento\Core\Helper\AbstractHelper)) {
        throw new \LogicException(
            $className . ' doesn\'t extends Magento\App\Helper'
        );
    }

    return $helper;
}

If you were to implement this yourself it seems Magento core is loading it in one of two ways:

Roll your own factory:

$objectManager = \Magento\Core\Model\ObjectManager::getInstance();

$helperFactory = $objectManager->get('\Magento\Core\Model\Factory\Helper');
$helper = $helperFactory->get('\PulseStorm\Commercebug\Helper\Data');

Or just grab it directly:

$helper = \Magento\Core\Model\ObjectManager::getInstance()->get('Magento\Core\Helper\Data');
8
  • 1
    +1 for useful information, but would you want to instantiate the factory directly like that? Or should a single helper factory be instantiated with the Object Manager as a cached class with get? Commented Nov 7, 2013 at 17:02
  • It's not totally clear, because the helper factory is inherited from \Mage\Core\Block\Abstract -- I think the intention is provide your own helper factory. It does not look like they're intentionally creating a singleton for the factory, though.
    – philwinkle
    Commented Nov 7, 2013 at 17:11
  • Sounds like I need/the best source is to trace how _helperFactory is injected into those objects and see how the core team instantiates it. Commented Nov 7, 2013 at 17:20
  • My simplification summary is incorrect as well as the constructor requires an instance of ObjectManager. I will edit momentarily.
    – philwinkle
    Commented Nov 7, 2013 at 17:27
  • See edit. It should work - hard to determine at this moment because my cli shell environment isn't loading the store config instance as expected. This should be enough to get you on the right track, though.
    – philwinkle
    Commented Nov 7, 2013 at 17:52
1

Try this way

$helper = \Magento\Framework\App\ObjectManager::getInstance()->get('Xx\Xx\Helper\Xx');
3
  • Usage of Object Manager directly is strictly discouraged.
    – sv3n
    Commented Feb 23, 2019 at 20:51
  • @sv3n could you please explain, what's the reason?. Thanks.
    – Thushan
    Commented Feb 24, 2019 at 15:59
  • 1
    Better use dependency injections instead ... answered here for example ... magento.stackexchange.com/questions/142352/…
    – sv3n
    Commented Feb 25, 2019 at 13:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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