5

I've recently created a module for Magento 2 which depends on various Magento framework classes through dependency injection like so:

// Vendor\Module\Helper\Debug
public function __construct(
    \Magento\Framework\App\Helper\Context $context,
    \Magento\Framework\Mail\Message $message,
    \Magento\Framework\Mail\Transport $transport,
    \Vendor\Module\Helper\Config $configHelper
) {
    ...
    parent::__construct($context);
}

This worked well until a third party module was installed that overrides the Message and Transport Framework classes in their di.xml:

<preference for="\Magento\Framework\Mail\Message" type="OtherVendor\Module\Model\Message"/>
<preference for="\Magento\Framework\Mail\Transport" type="OtherVendor\Module\Model\Transport"/>

Now my Module returns the following error

Recoverable Error: Argument 2 passed to Vendor\Module\Helper\Debug::__construct() must be an instance of Magento\Framework\Mail\Message, instance of OtherVendor\Module\Model\Message given

I've already tried deleting the var/generation folder, as well as refreshing and subsequently disabling the Magento cache.

What can I do to change my constructor so that it works either way? So by using either the Magento\Framework\Mail\Message core class or the override class by the third-party module.

2

You can use the Magento\Framework\Mail\MessageInterface interface in yours __construct method. If someone did rewrite of the class Magento\Framework\Mail\Message, then it shall implement this interface, but isn't obliged to extend a base class.

// Vendor\Module\Helper\Debug
public function __construct(
    \Magento\Framework\App\Helper\Context $context,
    \Magento\Framework\Mail\MessageInterface $message,
    \Magento\Framework\Mail\TransportInterface $transport,
    \Vendor\Module\Helper\Config $configHelper
) {
    ...
    parent::__construct($context);
}

You can read more info here I think third-party module developers make a low-quality rewrite and they don't think about how their module will works with another modules. In my opinion they should extend base class in their rewrite-class.

  • This works for me while retaining functionality as well. Although I'm not entirely satisfied, knowing that my code can break anytime if I inject the wrong Magento base class. Or does this mean I should only ever inject interface type objects? – sduif May 15 '17 at 13:44
  • @sduif You can read more info here I think third-party module developers make a low-quality rewrite and they don't think about how their module will works with another modules. In my opinion they should extend base class in their rewrite-class. – Siarhey Uchukhlebau May 15 '17 at 13:56
  • 1
    Thanks, looks like in my case I should've read up some more on Newable/non-injectable. In my case the injection wasn't even needed since I could just create new instances of \Magento\Framework\Mail\Message and \Magento\Framework\Mail\Transport when required. – sduif May 15 '17 at 14:08
  • @sduif I hope that means you're injecting \Magento\Framework\Mail\MessageInterfaceFactory $messageFactory and \Magento\Framework\Mail\TransportInterfaceFactory $transportFactory instead then, not getting them from ObjectManager. :) – Ryan Hoerr May 15 '17 at 15:31

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.