Как в Yii2 переопределить стандартный метод \yii\swiftmailer\Mailer::send()? Мне необходимо переопределить метод \yii\swiftmailer\Mailer::send(). Хочу что бы отправка писем осуществлялась через Gearman. Я создала класс, который унаследовала от \yii\swiftmailer\Mailer.class GearmanMailer extends \yii\swiftmailer\Mailer { private $_view = []; private $_viewPath; private $_message; public function send($message){ \Yii::$app->gearman->getDispatcher()->background('SendMailWorker', new JobWorkload([ 'params' => [ 'message' => $message, 'this' => $this ] ])); } } И переписала метод send(), как мне нужно. В нём теперь просто кидается задача в воркер гермэна. Воркер выглядит так:class SendMailWorker extends JobBase { public $thread_limit = 1; public function execute(\GearmanJob $job = null) { $params = $this->getWorkload($job)->getParams(); if (!$params['this']->beforeSend($params['message'])) { return false; } $address = $params['message']->getTo(); if (is_array($address)) { $address = implode(', ', array_keys($address)); } \Yii::info('Sending email "' . $params['message']->getSubject() . '" to "' . $address . '"', __METHOD__); if ($params['this']->useFileTransport) { $isSuccessful = $params['this']->saveMessage($params['message']); } else { $isSuccessful = $params['this']->sendMessage($params['message']); } $params['this']->afterSend($params['message'], $isSuccessful); return $isSuccessful; } } Код воркера - код стандартного метода \yii\swiftmailer\Mailer::send(). В итоге получаю ошибку:Exception 'yii\base\UnknownMethodException' with message 'Calling unknown method: app\libraries\shakura\gearman\GearmanMailer::sendMessage()' Почему-то в воркере у params['this'] не видит метода sendMessage(). Я же передала в воркер $this == экземпляр класса GearmanMailer, который наследуется от \yii\swiftmailer\Mailer, в котором определён метод sendMessage(). Что я делаю не так? p.s. Попробовала в воркере явно указать:$swift_mailer = new \yii\swiftmailer\Mailer(); ..... $isSuccessful = $swift_mailer->sendMessage($params['message']); В итоге получила:Exception 'yii\base\UnknownMethodException' with message 'Calling unknown method: yii\swiftmailer\Mailer::sendMessage()'
Проблема заключается в том, что в вашем воркере Gearman вы создаете новый экземпляр \yii\swiftmailer\Mailer() вместо использования экземпляра GearmanMailer, в котором определен метод sendMessage().
Чтобы исправить это, вам нужно передавать в воркер GearmanMailer вместо создания нового экземпляра Mailer. Используйте передачу экземпляра GearmanMailer в параметрах задачи Gearman и используйте его в воркере:
В вашем классе GearmanMailer измените функцию send следующим образом:
class GearmanMailer extends \yii\swiftmailer\Mailer { private $_view = []; private $_viewPath; private $_message; public function send($message) { \Yii::$app->gearman->getDispatcher()->background('SendMailWorker', new JobWorkload([ 'params' => [ 'message' => $message, 'this' => $this ] ])); } }
И в вашем воркере SendMailWorker измените следующим образом:
class SendMailWorker extends JobBase { public $thread_limit = 1; public function execute(\GearmanJob $job = null) { $params = $this->getWorkload($job)->getParams(); $mailer = $params['this']; if (!$mailer->beforeSend($params['message'])) { return false; } $address = $params['message']->getTo(); if (is_array($address)) { $address = implode(', ', array_keys($address)); } \Yii::info('Sending email "' . $params['message']->getSubject() . '" to "' . $address . '"', __METHOD__); if ($mailer->useFileTransport) { $isSuccessful = $mailer->saveMessage($params['message']); } else { $isSuccessful = $mailer->sendMessage($params['message']); } $mailer->afterSend($params['message'], $isSuccessful); return $isSuccessful; } }
Таким образом, вы будете использовать экземпляр GearmanMailer в вашем воркере Gearman, и метод sendMessage() будет вызываться успешно.
Проблема заключается в том, что в вашем воркере Gearman вы создаете новый экземпляр \yii\swiftmailer\Mailer() вместо использования экземпляра GearmanMailer, в котором определен метод sendMessage().
Чтобы исправить это, вам нужно передавать в воркер GearmanMailer вместо создания нового экземпляра Mailer. Используйте передачу экземпляра GearmanMailer в параметрах задачи Gearman и используйте его в воркере:
В вашем классе GearmanMailer измените функцию send следующим образом:
class GearmanMailer extends \yii\swiftmailer\Mailer{
private $_view = [];
private $_viewPath;
private $_message;
public function send($message) {
\Yii::$app->gearman->getDispatcher()->background('SendMailWorker', new JobWorkload([
'params' => [
'message' => $message,
'this' => $this
]
]));
}
}
И в вашем воркере SendMailWorker измените следующим образом:
class SendMailWorker extends JobBase{
public $thread_limit = 1;
public function execute(\GearmanJob $job = null)
{
$params = $this->getWorkload($job)->getParams();
$mailer = $params['this'];
if (!$mailer->beforeSend($params['message'])) {
return false;
}
$address = $params['message']->getTo();
if (is_array($address)) {
$address = implode(', ', array_keys($address));
}
\Yii::info('Sending email "' . $params['message']->getSubject() . '" to "' . $address . '"', __METHOD__);
if ($mailer->useFileTransport) {
$isSuccessful = $mailer->saveMessage($params['message']);
} else {
$isSuccessful = $mailer->sendMessage($params['message']);
}
$mailer->afterSend($params['message'], $isSuccessful);
return $isSuccessful;
}
}
Таким образом, вы будете использовать экземпляр GearmanMailer в вашем воркере Gearman, и метод sendMessage() будет вызываться успешно.