【问题标题】:Confused about Laravel 5 Queue for Sending Mail (Laravel 5.4)对 Laravel 5 发送邮件的队列感到困惑(Laravel 5.4)
【发布时间】:2017-02-19 18:59:17
【问题描述】:

我从 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('person@gmail.com')->send(new ForgotPassword($user->first_name));

我成功同步发送邮件(没有队列)。然后,我切换到队列:

Mail::to('person@gmail.com')->queue(new ForgotPassword($user->first_name));

最后,我从控制台运行这个命令:

php artisan queue:listen

当执行Mail::to 行时,会在Jobs 表中插入一行,但不会发送邮件。我该如何解决这个问题?

注意:ForgotPasswordMailable 类(应该是 Job 类?)。

【问题讨论】:

  • 当您跟踪日志tail -f storage/logs/laravel.log 时,您是否看到记录了任何错误?
  • Mail::to 行没有给出错误。但是php artisan queue:listen 命令导致SQLSTATE[22003]: Numeric value out of range: 1264 Out of range value for column 'attempts'
  • attempts 列的数据类型是什么?你可能想改成更大的,比如BIGINT
  • @DanielVerem 它是Jobs table 的标准列。
  • ForgotPassword 应该是Mailable。您的队列正在尝试发送邮件,但由于某种原因它失败了。您可以发布您的ForgotPassword 课程吗?此外,是否没有其他日志条目可以解释作业失败的原因?

标签: laravel laravel-5 laravel-queue laravel-mail


【解决方案1】:

同步send()和异步queue()之间的主要区别,就你的ForgotPassword对象而言,是当你排队发送对象时,它必须被序列化才能发送到队列中, 并在队列工作者处理它时取消序列化。

由于send() 工作正常,但queue() 发生错误,我们可以看到排队的作业被触发并被尝试处理,序列化/反序列化很可能有错误。

您的ForgotPassword 类可能正在使用SerializesModels 特征,因为这是 artisan 命令生成新可邮寄对象的方式。这个 trait 定义了 __sleep()__wakeup() 方法,它们修改了序列化和反序列化的工作方式。

__sleep方法实现时,PHP只会序列化__sleep方法返回的变量。在这种情况下,SerializesModels trait 提供的实现使用反射来遍历类上定义的属性,以提供一种特殊的方式来序列化 Eloquent 模型和集合。

因此,这意味着您的 ForgotPassword 类上未明确定义为该类属性的任何变量都不会被序列化,并且在处理队列作业并且该类被处理时将不可用未序列化。这是您的问题的最可能原因。当你的工作被尝试时,你的未序列化可邮寄实例没有它需要的数据,并且失败了。

有两种方法可以解决此问题。首先,如果您的 ForgotPassword 实际上不需要序列化任何模型,您可以删除 SerializedModels 特征。这将从类中删除__sleep() 定义,然后分配给类的所有变量,而不仅仅是实际定义的变量,都将被序列化,并且在类被反序列化时也可用。

第二个选项更合适、更明确,是在 ForgotPassword 类上实际定义您需要的属性。

如果你在你的类上定义属性,你可以在你的类上留下SerializesModels trait。但是,如果您实际上并没有序列化模型,我会继续删除它。如果不需要,则无需额外的序列化开销。

【讨论】:

    【解决方案2】:

    您可以使用 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 queue:listen 正在运行

    【讨论】:

    • Mail::queue 还是 Mail::send 在hande?队列不是运行句柄吗?所以我认为应该是 Mail::send。
    • 是的 Mail::queu,你可以在这里找到更多 laravel.com/docs/5.1/mail#queueing-mail
    【解决方案3】:

    您可能需要编辑机器上项目文件夹中的现有 .env 文件。 查找 .env 文件,通过 sublime text 打开并编辑。

    使用您要用来发送邮件的电子邮件 ID 和密码进行编辑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-05
      • 2019-11-19
      • 2014-11-19
      • 2017-10-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多