1

Is there a clean way to initiate and access a custom helper without using the constructor? Currently I instantiate the custom helper using the constructor of the model as shown here as the accepted answer.

This is great in most cases but now I would like to access a helper method on a model that adds a bit of functionality to the product model - extending \Magento\Catalog\Model\Product. It seems a bit overkill to overwrite this constructor so I am wondering if there is an alternative, acceptable way to do this? Can I just grab it directly via the ObjectManager or roll out my own factory like @philwinkle suggested here or is this not recommended?

3 Answers 3

2

the clean way to do it is to inject it in the constructor. Exactly what you are trying to avoid.
Also it can work if you instantiate it via objectManager, but this is discouraged. Even if there are classes instantiated via object manager in the core, this is not the recommended way to do it.
I'm not 100% sure, but I think the suggestion you mention from @philwinke is not valid anymore. That was for an older version. A lot has changed since then.
But even so, if you want to instantiate it via a helper factory, you still need to inject the helper factory in the constructor.
My recommendation is to inject it in the constructor, but if you absolutely don't want that, and you have an instance of the object manager available, instantiate it via object manager.

2
  • Thanks for your answer! Although it was not the answer I was hoping for I think you are right. Going to do this via the constructor and will look into fschmengler solution to completely get rid of this class.
    – rofavadeka
    Jul 15, 2015 at 14:05
  • @rofavadeka. Yep. This answers your question (somehow) but the other answer should solve your problem. :)
    – Marius
    Jul 15, 2015 at 14:11
7

What really is overkill, is extending the product model to add some functionality.

Depending on what you are trying to achieve, a plugin with interception might suit you better, this plugin again can use its own constructor injection.

Or even better, if possible, move your extended functionality to a completely different class.

Remember these principles:

  • Favor composition over inheritance
  • Don't f***ing rewrite the product model
2
  • Thanks for clear answer, I will remember and try to not rewrite the product model giving your proposed solution.
    – rofavadeka
    Jul 15, 2015 at 14:09
  • 1
    Just an update - Interception is awesome, worked great. Thank you for pointing me in the right direction. I will not have to rewrite the product model any more.
    – rofavadeka
    Jul 15, 2015 at 15:54
3

you can make a plugin for required block/model and extend as you want.

namespace Your\Namespace\Plugin;

class Test
{
    /**
     * @param $subject
     * @param \Closure $proceed
     * @param string $method
     * @param array $args
     * @return string
     */
    public function around__call(
        $subject,
        \Closure $proceed,
        $method,
        array $args
    ) {
        switch($method) {
            case 'iWantMyHelper':
                return $this->_getHelper($args);
        }
        return $proceed($method, $args);
    }

    protected function _getHelper($args)
    {
        return 'I am your helper!';
    }
}

you can call now this method from appropriate block/model/view: echo $this->iWantMyHelper();

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.