Magento 2 - 版本 2.2 - 覆盖 Zend_Mail_Transport_Sendmail

Magento 2 - Version 2.2 - Override Zend_Mail_Transport_Sendmail

大家好,

自从 Magento 2.2 发布以来,旧的覆盖 Zend_Mail_Transport_Sendmail 不再有效。

之前,etc/di.xml 和 model/Transport.php 中的重写有效。

<preference for="Magento\Framework\Mail\Transport" type="MyModul\MyPlugin\Model\Transport"/>

namespace MyModul\MyPlugin\Model;

class Transport extends \Zend_Mail_Transport_Sendmail implements \Magento\Framework\Mail\TransportInterface
{

    protected $_message;

    /**
     * @param \Magento\Framework\Mail\MessageInterface $message
     * @throws \Zend_Mail_Exception
     */
    public function __construct(
        \Magento\Framework\Mail\MessageInterface $message
    )
    {
        if (!$message instanceof \Zend_Mail) {
            throw new \InvalidArgumentException('The message should be an instance of \Zend_Mail');
        }

        parent::__construct('-f ' . 'test@test.de');
        $this->_message = $message;
    }



   /**
     * Send a mail using this transport
     *
     * @return void
     * @throws \Magento\Framework\Exception\MailException
     */
    public function sendMessage()
    {
        try {
            parent::send($this->_message);
        } catch (\Exception $e) {
            throw new \Magento\Framework\Exception\MailException(new \Magento\Framework\Phrase($e->getMessage()), $e);
        }
    }

    /**
     * @inheritdoc
     */
    public function getMessage()
    {
        return $this->_message;
    }

    /**
     * Send mail using PHP native mail()
     *
     * @access public
     * @return void
     * @throws Zend_Mail_Transport_Exception if parameters is set
     *         but not a string
     * @throws Zend_Mail_Transport_Exception on mail() failure
     */
    public function _sendMail()
    {

        /**
         *  revert changes from update to 2.1.7
         *
         *  mailing was not working with Envelope >= 2.1.7
         */
        if ($this->parameters === null) {
            set_error_handler(array($this, '_handleMailErrors'));
            $result = mail(
                $this->recipients,
                $this->_mail->getSubject(),
                $this->body,
                $this->header);
            restore_error_handler();
        } else {
            if(!is_string($this->parameters)) {
                /**
                 * @see Zend_Mail_Transport_Exception
                 *
                 * Exception is thrown here because
                 * $parameters is a public property
                 */
                #require_once 'Zend/Mail/Transport/Exception.php';
                throw new Zend_Mail_Transport_Exception(
                    'Parameters were set but are not a string'
                );
            }

            set_error_handler(array($this, '_handleMailErrors'));
            $result = mail(
                $this->recipients,
                $this->_mail->getSubject(),
                $this->body,
                $this->header,
                $this->parameters);
            restore_error_handler();
        }

        if ($this->_errstr !== null || !$result) {
            /**
             * @see Zend_Mail_Transport_Exception
             */
            #require_once 'Zend/Mail/Transport/Exception.php';
            throw new Zend_Mail_Transport_Exception('Unable to send mail. ' . $this->_errstr);
        }
    }
}

但现在我有点迷茫

我尝试创建一个插件,这似乎是现在应该做的方式。

<type name="\Magento\Framework\Mail\Transport">
    <plugin sortOrder="50" name="SendMailPlugin" type="MyModul\MyPlugin\Plugin\SendMailPlugin"/>
</type>

我还阅读了关于覆盖 "TransportInterface" 的内容,但我没有让它工作。我只需要它来调用我的插件上的构造函数。

提前致以最诚挚的问候和感谢

更新:

它现在又开始工作了。问题实际上只是 TransportInterface。我以为我已经尝试过了,或者它可能与 "generation" 缓存有关...

<preference for="Magento\Framework\Mail\TransportInterface" type="MyModul\MyPlugin\Model\Transport" />

因此,当覆盖 class 时,首选项需要指向接口。

我还没有让插件版本工作。在我的第一次尝试中,我什至不确定如何调用插件 "after__construct" 或 "afterConstruct" 中的方法。它还在调用 parent::contruct.

如果我最终让它工作,我会post它。

谢谢大家的帮助。

更新 2:

在这种情况下,插件解决方案是不可能的,因为无法为插件设置构造方法。

https://www.mageplaza.com/magento-2-module-development/magento-2-plugin-interceptor.html

好吧,首先你误解了插件在 Magento 2 中的作用。你试图将它用作 class 来覆盖另一个 class 但这是一种错误的方法。使用插件,您可以通过更改输入、输出或两者来将 public 方法包装在 class 中。您可以在 documentation

中阅读有关插件的更多信息

您正在寻找的是 M2 时尚的覆盖,因此您需要熟悉依赖注入和 preferences

你最初的做法是正确的。您是否在模块中正确配置了序列以确保您的模块在 Magento_Email 之后加载?验证 etc/config.php

中的序列

您可以尝试的另一件事是为 TransportInterface 设置首选项,而不是为传输模型设置首选项,尤其是当您的覆盖是全局的时。

您需要为模型使用插件 app/code/Magento/Email/Model/Transport.php

在模块的文件夹中创建你的di.xml

<config>
<type name="Magento\Email\Model\Transport">
  <plugin name="yourpluginforemail" type="\My\Module\Model\MyPlugin" sortOrder="1" />
</type>

你的插件文件应该看起来像

    <?php

namespace My\Module\Model;

class MyPlugin
{
    public function afterSendEmail($subject, $result)
    {
        return 'some thing else'
    }
}
?>

或者,如果需要,您可以通过创建自己的文件并设置顺序来覆盖此文件

die.xml 在你的模块中

module.xml

<module name="My_Module" setup_version="2.0.1">
            <sequence>
                <module name="Magento_Email"/>

            </sequence>
        </module>

然后它将覆盖它。

所以有两种方法 - 覆盖 class 或通过 "after"、"before" "around" 插件

的一种方法

Bartosz Herba

解决方案在单次拍摄中有效。谢谢。