【问题标题】:How to queue Laravel 5.7 "email verification" email sending如何排队 Laravel 5.7“电子邮件验证”电子邮件发送
【发布时间】:2019-03-09 17:46:11
【问题描述】:

Laravel 5.7 包含的“电子邮件验证”功能运行良好,但异步电子邮件发送(在用户注册或重新发送链接页面期间)并不理想。

在 Laravel 5.7 中,有没有办法通过队列发送电子邮件验证电子邮件而无需重写整个电子邮件验证?

【问题讨论】:

  • 我认为目前这是不可能的。新 trait 发送 this email,目前无法排队。

标签: laravel queue email-verification laravel-5.7


【解决方案1】:

没有内置方法,但您可以通过扩展和覆盖轻松实现。

首先,创建一个扩展内置通知的新通知,并实现 ShouldQueue 协定(以启用排队)。以下类假设您在app/Notifications/VerifyEmailQueued.php 创建通知:

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Auth\Notifications\VerifyEmail;

class VerifyEmailQueued extends VerifyEmail implements ShouldQueue
{
    use Queueable;

    // Nothing else needs to go here unless you want to customize
    // the notification in any way.
}

现在您需要告诉框架使用您的自定义通知而不是默认通知。您可以通过覆盖 User 模型上的 sendEmailVerificationNotification() 来做到这一点。这只是改变了发送的通知。

public function sendEmailVerificationNotification()
{
    $this->notify(new \App\Notifications\VerifyEmailQueued);
}

【讨论】:

  • 工作得像个骗子!
  • 这比公认的答案简单得多,而且有效
  • 这个工作,但是当点击验证链接(通过电子邮件发送)时,它会重定向到 403,无效签名页面。 (Laravel 6)
  • @IrfanGondal 通知现在将排队,因此通知中的 URL 将使用您的环境文件中的 APP_URL 构建。该 APP_URL 将需要匹配最终的 url。因此,例如,如果您的网站位于 https,则需要确保您的 APP_URL 也是 https
【解决方案2】:

是的!这是可能的。为此,您必须在您的App\User 中重写sendEmailVerificationNotification。此方法由 Illuminate\Auth\MustVerfiyEmail 特征提供。方法sendEmailVerificationNotification 通过发送Illuminate\Auth\Notifications\VerifyEmail 通知类中定义的电子邮件来通知创建的user

// This is the code defined in the sendEmailVerificationNotification
public function sendEmailVerificationNotification()
{
    $this->notify(new Notifications\VerifyEmail);
}

您可以将此方法更改为不直接通知用户。您将必须定义一个 Job,您将在 sendEmailVerificationNotification 方法中忽略它,而不是通知创建的用户。

Job 类中,您将创建一个handle 方法,您可以在其中将电子邮件发送到user,但您必须将$user 提供给作业,这可以通过将其作为参数传递来执行dispatch 方法如下:

public function sendEmailVerificationNotification()
{
    VerifyEmail::dispatch($this);
}

$this 代表创建的userApp\Jobs\VerififyEmail 作业(您将创建)将在其__construct 中接收传递给dispatch 的所有参数

VerifyEmail 的代码如下所示:

namespace App\Jobs;

use App\User;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Auth\Notifications\VerifyEmail;

class VerifyEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    protected $user;

    public function __construct(User $user)
    {
        $this->user = $user;
    }

    public function handle()
    {
        // Here the email verification will be sent to the user
        $this->user->notify(new VerifyEmail);
    }
}

【讨论】:

  • 感谢您的回复,它有效!由于双重类名声明,只需要重命名 Job 类 QueuedVerifyEmail。
  • 不客气。即使两个类具有相同的名称,因为它们位于不同的命名空间 App\Jobs\VerifyEmailIlluminate\Auth\Notification\VerifyEmail 它不会产生任何问题
  • 您可以通过将 Laravel 的类别名为另一个名称来使用相同的类名,例如:use Illuminate\Auth\Notifications\VerifyEmail as VerifyEmailNotification;handle 方法 $this->user->notify(new VerifyEmailNotification);。在我看来,这有点清洁,但这只是吹毛求疵。
【解决方案3】:

如果您要在控制器中手动注册用户,我的解决方案是。 Laravel 已经创建了 Registered 事件及其监听器 SendEmailVerificationNotification。

-首先在应用程序中配置队列 在 .env 文件中更新 QUEUE_CONNECTION=database。 更多队列文档请阅读https://laravel.com/docs/6.x/queues

  • 通过php artisan queue:table发布队列表

  • php artisan migrate

  • php artisan make:job EmailVerificationJob

  • 在 EmailVerificationJob.php 中添加公共变量

    公开的$用户;

  • 在 EmailVerificationJob.php 构造函数中

    公共函数 __construct(用户 $user) { $this->user = $user; }

  • 在EmailVerificationJob.php句柄函数中写event(new Registered($this->user))

  • 如果用户创建成功,请在您的控制器中添加此代码以使作业正常工作。

    EmailVerificationJob::dispatch($user) ->延迟(现在()->addSeconds(5)); 这里作业延迟 5 秒。

  • 最后你必须启动队列工作者php artisan queue:work --tries=3。这里的尝试是指队列应该尝试多少次。

更新#1

我在 Laravel 8 中使用的这个解决方案。

首先创建 SendEmailVerificationNotification 通知类

php artisan make:notification SendEmailVerificationNotification

app/Notifications/SendEmailVerificationNotification.php 文件内容会是这一项。这里我们将扩展 Laravel 默认的 SendEmailVerificationNotification 类并实现应该队列

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class SendEmailVerificationNotification extends \Illuminate\Auth\Listeners\SendEmailVerificationNotification implements ShouldQueue
{
    use Queueable;
}

最后一步是编辑 EventServiceProvider 类 $listen 数组。注释掉注册事件的默认通知并添加我们创建的自定义通知。

use App\Notifications\SendEmailVerificationNotification as QueuedSendEmailVerificationNotification;
use Illuminate\Auth\Events\Registered;
//use Illuminate\Auth\Listeners\SendEmailVerificationNotification;

protected $listen = [
        Registered::class => [
//            SendEmailVerificationNotification::class,
            QueuedSendEmailVerificationNotification::class
        ],

];

【讨论】:

    【解决方案4】:

    解决方法很简单:

    Steps:

    1. 配置队列驱动程序

    2. 转到 --> Illuminate\Auth\Notifications\VerifyEmail

    3. 实现“ShouldQueue”接口并在上述类上添加特征“Queueable”,即“VerifyEmail”,如下所示:

    类 VerifyEmail 扩展通知实现 ShouldQueue{ 使用可排队

    .... …… ... }

    3.就是这样

    接口和特征的路径: 使用 Illuminate\Contracts\Queue\ShouldQueue; 使用 Illuminate\Bus\Queueable;

    也请查看文档: https://laravel.com/docs/5.7/notifications#queueing-notifications

    【讨论】:

    • 修改 laravel 类不是一个好主意,这就是为什么上面的解决方案建议通过扩展和覆盖来做到这一点。
    • 对 laravel vendor 文件夹中的文件进行更改不是一个好主意,因为在下一个 composer update 命令中,您对 vendor 文件夹中文件的更改将被删除。
    猜你喜欢
    • 2019-10-18
    • 2019-03-05
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2022-08-13
    • 2019-03-05
    • 2019-11-21
    • 2019-03-04
    相关资源
    最近更新 更多