如何在Laravel 5.5中监听messageSent事件

6

你好,我是一名初学者,关于Laravel中的事件和监听器,请告诉我如何实现以下目标:

目标:

向用户发送电子邮件,并了解是否已成功发送电子邮件。

我的理解:

Laravel内置了事件Illuminate\Mail\Events\MessageSent,在电子邮件发送后触发该事件,我需要编写监听器来监听该事件。

我的操作:

发送电子邮件:

Mail::to($receiverAddress)->send(new SendNewUserPassword($content));

这个很好。已成功向用户发送电子邮件。
为了监听messageSent事件,我创建了这个监听器:
<?php

namespace App\Listeners;

use Illuminate\Mail\Events\MessageSent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class LogSentMessage
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  MessageSent  $event
     * @return void
     */
    public function handle(MessageSent $event)
    {
        return $event->message;
    }
}  

注册事件:

protected $listen = [
    'App\Events\Event' => [
        'App\Listeners\EventListener',
    ],

    'Illuminate\Mail\Events\MessageSent' => [
        'App\Listeners\LogSentMessage',
    ],
];

在控制器中:
event(new MessageSent())  

请指导我如何从控制器中返回Listener处理的消息。如果我上述的方法是错误的,请告诉我如何实现它。我正在为一个API使用它,所以如果发送邮件成功/失败,我想知道。
4个回答

7
您可以从控制器传递数据到可发送对象(Mailable),并且再从可发送对象(Mailable)传递到监听器。例如,我有一个名为"SendOrder"的模型,用于跟踪电子邮件的状态,所以我从控制器将此模型传递给监听器。以下是您需要从头开始执行的步骤:

在您的控制器中

将模型传递给可发送对象(Mailable)的构造函数

$send_order = SendOrder::create(['status' => 'received', 'email' => 'foo@example.com']);

Mail::to($receiverAddress)->send(new SendNewMail($send_order));

在可发送的邮件类中SendNewMail

可发送邮件的类有一个方法withSwiftMessage(),您可以使用它来存储变量/对象,以便稍后从监听器中访问。

我们将创建一个构造函数,将模型传递给build()方法,在其中执行withSwiftMessage()以便稍后存储。

use App\SendOrder;

class SendNewMail extends Mailable
{
     protected $send_order;

     public function __construct( SendOrder $send_order )
     {
         $this->send_order = $send_order;
     }
     public function build()
     {
         $send_order = $this->send_order;
         $this->withSwiftMessage(function ($message) use($send_order) {
               $message->send_order = $send_order;
         });

         // Do more stuffs

     }
}

创建监听器

在文件app/Providers/EventServiceProvider.php中注册事件和监听器

protected $listen = 
    'Illuminate\Mail\Events\MessageSent' => [
        'App\Listeners\LogSentMessage',
    ],
];

现在执行以下命令:

php artisan event:generate

这将自动生成新的监听器app\Listeners\LogSentMessage,其中包含与内置事件Illuminate\Mail\Events\MessageSent连接的模板代码。

在您的监听器LogSentMessage

您可以通过以下方式访问模型:

public function handle(MessageSent $event)
{
    $send_order = $event->message->send_order;
    $send_order->update(['status' => 'sent']);
}

我之前不知道可以从可邮寄对象传递数据到监听器。这让我的一天变得美好了。谢谢你。 - bakis
注意:Laravel 9将SwiftMailer替换为Symfony Mailer。withSwiftMessage变成了withSymfonyMessage - 更多详情请参见此处 - Cameron Wilby

2
在你的 EventServiceProvider 中添加你的事件和监听器。
protected $listen = [
       'Illuminate\Notifications\Events\NotificationSent' => [
       'App\Listeners\YourListenerClass',
    ],
]; 

并且在 YourListnerClass 中

public function handle(NotificationSent $event)
{

 //access your $event data here 
 //which includes notification details too

}

1
这就是我所做的。我在我的问题中解释了这一点。现在,当事件被触发时,我想将该消息返回给控制器。 - Himakar
事件是异步的。它在某些事情发生时触发。 - user2749200
是的,它会触发并且我们有侦听器来监听它,但如何捕获该触发消息并将其返回给控制器方法呢? - Himakar
你想要做什么? - user2749200
我有一个API用于发送电子邮件,当从Laravel发送电子邮件时,我希望返回来自该API中messageSent事件触发的消息。上面我解释了我在代码中写的一切。 - Himakar

1

执行php php artisan event:generate 命令将为您生成代码:App\Listeners\LogSentMessage

例如,编辑该文件:

public function handle(MessageSent $event)
{
    dd($event->message->getBody(), $event->message->toString());
}

1

我曾经陷入困境,一直试图让我的EventServiceProvider将Illuminate\Mail\MessageSent事件注册到本地监听器。每次我尝试运行 php artisan event:generate 都会出现以下问题:

Your application doesn't have any events matching the given criteria.

我终于发现我的EventService提供程序正在使用。
use Illuminate\Support\ServiceProvider;

当我将它切换为使用 use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; 时,事件已经成功注册了!也许这会对某些人有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接