对Laravel 5发送邮件队列感到困惑(Laravel 5.4) [英] Confused about Laravel 5 Queue for Sending Mail (Laravel 5.4)

查看:159
本文介绍了对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('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类?).

解决方案

就您的ForgotPassword对象而言,同步send()和异步queue()之间的主要区别是,当您将队列用于发送的对象,必须序列化后才能发送到队列,并且在队列工作程序处理该对象时不进行序列化.

由于send()工作正常,但是queue()发生错误,并且我们可以看到已排队的作业已被触发并正在尝试进行处理,所以序列化/反序列化很可能出错. /p>

您的ForgotPassword类可能使用的是SerializesModels特征,因为artisan命令是如何生成新的可邮寄对象的.此特征定义 __sleep() __wakeup() 方法,这些方法修改了序列化和反序列化的工作方式.

实现__sleep方法时,PHP将仅序列化__sleep方法返回的变量.在这种情况下,SerializesModels特质提供的实现使用Reflection来遍历类中定义的属性,以提供一种特殊的方式来序列化Eloquent模型和集合.

因此,这意味着ForgotPassword类上任何未明确定义为该类属性的变量都不会被序列化,并且在处理排队的作业并且该类为未序列化.这是您遇到问题的最可能原因.尝试工作时,未序列化的可邮寄实例没有所需的数据,并且发生故障.

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

第二种方法更合适,更明确,它实际上是定义您在ForgotPassword类上需要的属性.

如果在类上定义属性,则可以在类上保留SerializesModels特性.但是,如果您实际上并未序列化模型,那么我将继续删除它.如果不需要,不需要额外的序列化开销.

I upgrade from Laravel 4.1 to 5.4. Queue migration is difficult.

Firstly, I commented out iron route from routes:

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

Then, I configured database driver and migrated jobs table:

php artisan queue:table
php artisan migrate

I changed Mail::queue codes to the Mailables like this:

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

I succeeded to send mails synchronously (without queue). Then, I switched to queue:

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

And lastly, I run this command from console:

php artisan queue:listen

When a Mail::to line is executed, a row is inserted to the Jobs table but mail isn't sent. How can I solve this problem?

Note: ForgotPassword is a Mailable class (should be a Job class?).

解决方案

The main difference between the synchronous send() and the asynchronous queue(), as far as your ForgotPassword object is concerned, is that when you queue the object for sending, it must be serialized to be sent to the queue, and unserialized when the queue worker processes it.

Since send() works fine, but an error is occurring with queue(), and we can see that the queued job is fired and being attempted to be processed, there is most likely an error in the serialization/unserialization.

Your ForgotPassword class is probably using the SerializesModels trait, since that is how the artisan command generates a new mailable object. This trait defines __sleep() and __wakeup() methods, which modify how serialization and unserialization work.

When the __sleep method is implemented, PHP will only serialize the variables that are returned by the __sleep method. In this case, the implementation provided by the SerializesModels trait uses Reflection to go through the properties defined on the class to provide a special way to serialize Eloquent models and collections.

Because of this, this means that any variables on your ForgotPassword class that are not specifically defined as a property on the class will not get serialized, and it will not be available when the queued job is processed and the class is unserialized. This is the most likely reason for your issue. When your job is being attempted, your unserialized mailable instance doesn't have the data it needs, and is failing.

There are two ways to resolve this. First, if your ForgotPassword does not actually need to serialize any models, you can remove the SerializedModels trait. This will remove the __sleep() definition from the class, and then all variables assigned on the class, not just those actually defined, will be serialized, and will also be available when the class is unserialized.

The second option, which is more appropriate and more explicit, is to actually define the properties you need on your ForgotPassword class.

If you define the properties on your class, you could leave the SerializesModels trait on your class. However, if you aren't actually serializing models, I'd go ahead and remove it. No need for the extra serialization overhead if you don't need it.

这篇关于对Laravel 5发送邮件队列感到困惑(Laravel 5.4)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆