26

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)

31

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.

  • 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 Jul 17 '15 at 15:03
  • @Anton Kril if we use helper in template, like $this->helper('Magento\Catalog\Helper\Image'), it follows the best practice? – Khoa TruongDinh Apr 24 '16 at 10:09
  • 2
    No, it does not. Templates should only reference blocks. Helpers should be avoided – Anton Kril Apr 25 '16 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;            
}
  • This is the correct answer - great sleuthing; was not totally obvious to me even after a lot of digging. – philwinkle Nov 8 '13 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 Nov 8 '13 at 19:15
  • @Marius hahaha this is not that uncommon - Alan's blog explains it to some extent. – philwinkle Nov 8 '13 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 Nov 8 '13 at 21:28
  • Oh...and by the way. +1. Good question & nice answer. – Marius Nov 8 '13 at 21:29
7

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');
  • 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? – Alan Storm Nov 7 '13 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 Nov 7 '13 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. – Alan Storm Nov 7 '13 at 17:20
  • My simplification summary is incorrect as well as the constructor requires an instance of ObjectManager. I will edit momentarily. – philwinkle Nov 7 '13 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 Nov 7 '13 at 17:52
0

Try this way

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

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.