1

In this https://github.com/magento/magento2/blob/2.3/app/code/Magento/Contact/view/frontend/templates/form.phtml you see something like this

$this->helper('Magento\Contact\Helper\Data')->getUserEmail())

In code quality checks I see $this in templates is now deprecated

What's the recommended approach?

3
  • Check this answer magento.stackexchange.com/a/150945/76597 In my opinion that's the correct approach
    – HelgeB
    Jun 16, 2019 at 8:32
  • That's the route I took (magento.stackexchange.com/a/206077/70343) however you have to independently inject each helper which means more work. I wondered whether there was something which you could pass an argument to that basically works in the same way but does use $this context. A helper helper lol. I guess not. Jun 16, 2019 at 9:44
  • the correct path is via view_models right now Feb 11, 2020 at 20:05

3 Answers 3

2

I would say that either extending the block or creating a view model that injects the helper, then exposes proxy methods for the data you want to access would be the correct way to do it.

Using helpers directly in template files is generally frowned upon since you are introducing business logic into the template. This just seems like old ported code from M1, that will be refactored into the new design patterns at some point in the future.

But if you really wanted a function that behaved the same way, you could reimplement it into your block since all the helper function does is load the class through object manager, you can find the implementation here https://github.com/magento/magento2/blob/2.3-develop/lib/internal/Magento/Framework/View/TemplateEngine/Php.php#L120

5
  • Creating a viewModel is the valid approach if you ask me Feb 11, 2020 at 19:57
  • @GosuPrzmak provide example? Feb 11, 2020 at 20:27
  • @DominicXigen Here you go bro Feb 11, 2020 at 22:11
  • @DominicXigen please change your mark if the answer below helps you :) Feb 12, 2020 at 12:06
  • @GosuPrzmak nice and I completely understand your approach Feb 12, 2020 at 13:55
2

This breaks down into 3 simple steps.

I assume that you are reffering to the contactForm block in the contact_index_index.xml

1) In one of your modules or designs create a contact_index_index.xml in your layout folder

For module

Vendor/Module/view/frontend/layout

Remeber about setting sequence in module.xml for Customer_Contact

For design

Vednor/Theme/Magento_Contact/layout

contact_index_index.xml

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceBlock name="contactForm" template="Magento_Contact::form.phtml">
              <arguments>
                   <argument name="view_model" xsi:type="object">Vendor\Module\ViewModel\Contact</argument>
              </arguments>
        </block>
    </body>
</page>

2) Create your ViewModel -> Vendor\Module\ViewModel\Contact.php

Contact.php

<?php declare(strict_types=1);

namespace Vendor\Module\ViewModel;

use Magento\Framework\View\Element\Block\ArgumentInterface;
use Magento\Contact\Helper\Data as ContactHelperData;

class Contact implements ArgumentInterface {

    /** @var ContactHelperData */
    private $contactHelperData;    

    /** @param ContactHelperData */
    public function __construct(ContactHelperData $contactHelperData)
    {
        $this->contactHelperData = $contactHelperData;
    }    

    /** @return ContactHelperData */
    public function getContactHelperData()
    {
        return $this->contactHelperData;
    }
}

3) Use the view_model in your template.

Extend old template. Seems you already did it. Do it in anyway you want I will post an example for theme.

Create the file in

 Vendor\Theme\Magento_Contact\templates\form.phtml

now in your form.phtml

/** @var Vendor\Module\ViewModel\Contact $viewModel */
$viewModel = $block->getData('view_model');    
/** @var Magento\Contact\Helper\Data $viewModel */
$helper = $viewModel->getContactHelperData();

Bang, that's all :)

Now you can use the helper within the block without worring about the explosion after near future updates :)

Ofc do the text formatting, it's getting late I could made some typos :)

0

I quite like the original solution

To elaborate in theory


namespace Xigen\Demo\Block;

class Test extends \Magento\Framework\View\Element\Template
{

    /**
     * Constructor
     * @param \Magento\Framework\View\Element\Template\Context  $context
     * @param array $data
     */
    public function __construct(
        \Magento\Framework\View\Element\Template\Context $context,
        \Magento\Framework\ObjectManagerInterface $helperFactory,
        array $data = []
    ) {
        $this->_helperFactory = $helperFactory;
        parent::__construct($context, $data);
    }

     /**
     * Get helper singleton
     * @param string $className
     * @return \Magento\Framework\App\Helper\AbstractHelper
     * @throws \LogicException
     */
    public function helper($className)
    {
        $helper = $this->_helperFactory->get($className);
        if (false === $helper instanceof \Magento\Framework\App\Helper\AbstractHelper) {
            throw new \LogicException($className . ' doesn\'t extends Magento\Framework\App\Helper\AbstractHelper');
        }

        return $helper;
    }
}

Then in template phtml should be as easy as:

$block->helper(\Magento\Contact\Helper\Data::class)->getUserEmail()

3
  • Well tbh I like it also, but nowadays approach is via viewModels and extending blocks should happen only when you want to customize the block cache or rewriting old classes. Feb 12, 2020 at 19:47
  • @GosuPrzmak completely agree you've gone with the official approach. However sometimes less is more. With original solution you would not need to inject further classes if for example you are calling from multiple. That's why I think it's a really elegant solution. Although you've provided really well written alternative. I think others will find both suggestions useful. Feb 12, 2020 at 21:14
  • This solutions is minimal solution and efective.Its solved my M2 coding standerd issue very quickly. Thanks. May 27, 2020 at 12:14

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.