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
解决方案在单次拍摄中有效。谢谢。
大家好,
自从 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
解决方案在单次拍摄中有效。谢谢。