7

What is the correct way of getting a helper in a template file of a custom block?

In Magento_Search module there is a block:

<referenceContainer name="header-wrapper">
    <block class="Magento\Framework\View\Element\Template" 
        name="top.search" 
        as="topSearch" 
        template="Magento_Search::form.mini.phtml" 
    />
</referenceContainer>

In the form.mini.phtml template I found this way of getting helper object:

$helper = $this->helper('Magento\Search\Helper\Data');

I read in many tutorials that I should inject an instance of the helper in the constructor __construct() of the block. This can be found in dozens of Magento template files. But in some templates helpers are retrieved with $this->helper(...) method.

Just like in the top.search block from my example. It is an instance of the generic Magento\Framework\View\Element\Template class so probably that's why the helper had to be retrieved this way (because we can't inject it in the constructor).

1.

So can I use this $this->helper(...) method in my custom blocks instead of injecting helpers through constructor? Or is it a bad practice and it should be avoided? It's less code and more convenient.

2.

Where is that helper method implemented? I couldn't find it in the Magento\Framework\View\Element\Template class nor in its parent classes.

1

3 Answers 3

4

The way to inject a helper into the Template model via DI (Dependency Injection) is to:

  1. Extend the Magento\Framework\View\Element\Template block with your own (eg: class MyBlock extends \Magento\Framework\View\Element\Template)
  2. Then in the MyBlock constructor, inject your Helper:

    <?php
    /**
     * @var \Magento\Search\Helper\Data $helper
     */
    protected $helper;
    
    public function __construct(
      \Magento\Framework\View\Element\Template\Context $context,
      \Magento\Search\Helper\Data $helper,
      array $data = []
    ) {
        $this->helper = $helper;
        parent::__construct($context, $data);
    }
    
  3. Then add a getter method to MyBlock:

    <?php
    function getDataHelper() {
        return $this->helper;
    }
    
  4. Define your block to use the new MyBlock you created (instead of Template):

    <block class="Your\ModuleBlocks\MyBlock" 
      name="top.search" 
      as="topSearch" 
      template="Magento_Search::form.mini.phtml" 
     />
    
  5. Then in your block .pthml template you can access the helper this way:

    <?php $block->getDataHelper() ?>
    

It's certainly easier to just call $this->helper() in the .phtml template.

As for part 2 of your question, Magento\Framework\View\Element\Template is the $block object in your .phtml template, and you are correct: it does not have the helper() method.

However, the $this object in a .phtml template is the Magento\Framework\View\TemplateEngine\Php object, which does have that method (as noted in another answer).

(Using this helper() method requires that your helper extend the Magento\Framework\App\Helper\AbstractHelper class, it should be noted.)

1
  • This is valuable, thanks for the detailed explanation about $block and $this Commented Nov 25, 2019 at 23:52
1
  1. Most of the developers will tell you it is not convenient. Due to the body of function helper. It returns something like this: ObjectManager->get(...) (Singleton).

  2. In Magento 2.1.1 it is located in: vendor/magento/framework/View/TemplateEngine/Php.php ~Line: 120

  3. Nevertheless until Magento will stop using this function in phtml- files, i will do so.

1

View helpers should be simple and easy to use methods, which can be used in any template, without a need to create a custom block for this purpose - for me it is very convenient.

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.