Запутался в очереди Laravel 5 для отправки почты (Laravel 5.4)

Я обновляюсь с Laravel 4.1 до 5.4. Миграция очереди затруднена.

Во-первых, я закомментировал iron маршрут из маршрутов:

Route::post('queue/receive', function()
{
    return Queue::marshal();
});

Затем я настроил драйвер базы данных и перенес таблицу jobs:

php artisan queue:table
php artisan migrate

Я изменил Mail::queue коды на Mailables следующим образом:

Mail::to('[email protected]')->send(new ForgotPassword($user->first_name));

Мне удалось отправить почту синхронно (без очереди). Затем я переключился на очередь:

Mail::to('[email protected]')->queue(new ForgotPassword($user->first_name));

И, наконец, я запускаю эту команду из консоли:

php artisan queue:listen

При выполнении строки Mail::to строка вставляется в таблицу Jobs, но почта не отправляется. Как я могу решить эту проблему?

Примечание: ForgotPassword — это класс Mailable (должен быть класс Job?).


person horse    schedule 19.02.2017    source источник
comment
Когда вы просматриваете свои журналы tail -f storage/logs/laravel.log, видите ли вы какие-либо зарегистрированные ошибки?   -  person Daniel Verem    schedule 21.02.2017
comment
Mail::to строка не выдает ошибку. Но команда php artisan queue:listen приводит к SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'attempts'.   -  person horse    schedule 21.02.2017
comment
Какой тип данных для столбца attempts? Вы можете изменить его на что-то большее, например BIGINT.   -  person Daniel Verem    schedule 21.02.2017
comment
@DanielVerem Это стандартный столбец таблицы Jobs.   -  person horse    schedule 21.02.2017
comment
Да. Итак, вот что я думаю, что происходит. По какой-то причине ваша работа терпит неудачу и повторяется. Поскольку у вас не установлен атрибут максимального количества повторных попыток в вашем классе заданий, количество повторных попыток превысило размер, который может содержать столбец attempts, т.е. tinyInteger. Один из способов решить эту проблему — добавить public $tries = 5; или другое число к вашему классу работы. @лошадь   -  person Daniel Verem    schedule 21.02.2017
comment
Пожалуйста, найдите почтовый драйвер, из .env это должен быть smtp, а не журнал   -  person Chintan7027    schedule 23.02.2017
comment
Миграция по умолчанию, созданная для очереди laravel, имеет небольшое ограничение для столбца попытки, поэтому выдает предупреждение   -  person Chintan7027    schedule 23.02.2017
comment
ForgotPassword должно быть Mailable. Ваша очередь пытается отправить почту, но по какой-то причине это не удается. Можете ли вы опубликовать свой ForgotPassword класс? Кроме того, нет ли других записей в журнале, которые могли бы объяснить, почему задание не выполняется?   -  person patricus    schedule 24.02.2017
comment
В порядке. Журнала работы нет. Забыли пароль..   -  person horse    schedule 25.02.2017
comment
@patricus У меня проблема. Я забыл определить частные переменные в файле mailable. Теперь это работает. Напишите ответ, 50 реп твоё.   -  person horse    schedule 25.02.2017


Ответы (3)


Основное различие между синхронным send() и асинхронным queue(), что касается вашего объекта ForgotPassword, заключается в том, что когда вы ставите объект в очередь для отправки, он должен быть сериализован для отправки в очередь и десериализован, когда обработчик очереди его обрабатывает. .

Поскольку send() работает нормально, но с queue() возникает ошибка, и мы видим, что задание в очереди запущено и пытается быть обработано, скорее всего, есть ошибка в сериализации/десериализации.

Ваш класс ForgotPassword, вероятно, использует трейт SerializesModels, так как именно так команда artisan создает новый почтовый объект. Этот трейт определяет __sleep() и __wakeup(), которые изменяют работу сериализации и десериализации.

Когда реализован метод __sleep, PHP будет сериализовать только те переменные, которые возвращаются методом __sleep. В этом случае реализация, предоставляемая трейтом SerializesModels, использует Reflection для просмотра свойств, определенных в классе, чтобы обеспечить особый способ сериализации моделей и коллекций Eloquent.

Из-за этого это означает, что любые переменные в вашем классе ForgotPassword, которые не определены специально как свойство класса, не будут сериализованы и не будут доступны при обработке задания в очереди и десериализации класса. Это наиболее вероятная причина вашей проблемы. Когда ваша работа выполняется, ваш несериализованный почтовый экземпляр не имеет необходимых данных и дает сбой.

Есть два способа решить эту проблему. Во-первых, если вашему ForgotPassword на самом деле не нужно сериализовать какие-либо модели, вы можете удалить трейт SerializedModels. Это удалит определение __sleep() из класса, а затем все переменные, присвоенные классу, а не только те, которые фактически определены, будут сериализованы, а также будут доступны, когда класс не сериализован.

Второй вариант, который является более подходящим и более явным, заключается в том, чтобы фактически определить свойства, которые вам нужны, в вашем классе ForgotPassword.

Если вы определяете свойства в своем классе, вы можете оставить черту SerializesModels в своем классе. Однако, если вы на самом деле не сериализуете модели, я бы удалил его. Нет необходимости в дополнительных накладных расходах на сериализацию, если они вам не нужны.

person patricus    schedule 26.02.2017

Вы можете отправлять почту, используя очередь laravel, см. пример,

Определить задание

public function handle()
{
        $mail_meta_data = $this->send_data;
        $require_data = $this->require_data;
        Mail::queue($mail_meta_data['view_name'], ['data'=>$require_data], function($message) use ($mail_meta_data, $require_data) {
            //$message->from($mail_meta_data['to'], $mail_meta_data['name']);

            $message->to($mail_meta_data['to'])->subject($mail_meta_data['subject']);
        });
 }

Вызвать задание

dispatch(new SendEmailNotification($mail_meta_data, $require_data));

.env

 MAIL_DRIVER=smtp
 MAIL_HOST=smtp.sendgrid.net
 MAIL_PORT=587
 MAIL_USERNAME=smtp_username
 MAIL_PASSWORD=smptp_password
 MAIL_ENCRYPTION=tls

 APP_EMAIL=email sent from
 APP_NAME=Name of Email sender

Примечание

  1. Убедитесь, что вы установили вышеуказанную конфигурацию почты в файле .env или в config/mail.php.
  2. Также запущена очередь php artisan: listen
person Chintan7027    schedule 23.02.2017
comment
Mail::queue или Mail::send в руке? Разве очередь не управляется дескриптором? Поэтому я думаю, что это должен быть Mail::send. - person horse; 23.02.2017
comment
да Mail::queu, вы можете найти больше здесь laravel.com/docs/5.1/mail #очередь-почта - person Chintan7027; 23.02.2017

Возможно, вам придется отредактировать существующий файл .env в папке проекта на вашем компьютере. Найдите файл .env, откройте его через возвышенный текст и отредактируйте.

Отредактируйте с помощью идентификатора электронной почты и пароля, с которым вы собираетесь отправлять письма.

person A.n1014    schedule 22.02.2017