Himakar
Himakar

Reputation: 345

How to listen messageSent event in laravel 5.5

I am a beginner at events and listeners in Laravel. So please explain to me how to achieve this:

Aim:

Send an email to the user. And know whether the email is sent or not.

My Understanding:

Laravel has an in-built event Illuminate\Mail\Events\MessageSent to fire after an email is sent and I have to write a listener to listen to the event.

What I did:

To send an email :

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

This is working fine. Able to send emails to users successfully.

To listen to the messageSent event, I created this listener:

<?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;
    }
}  

To Register Event:

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

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

In Controller:

event(new MessageSent())  

Please guide me how to return the message handled in Listener from controller. If my above approach is wrong explain to me how to achieve it. This I am using for an API, so if sending mail is success/fail I want to know.

Upvotes: 6

Views: 8459

Answers (4)

blake
blake

Reputation: 103

I was stuck forever and ever trying to get my EventServiceProvider to register the Illuminate\Mail\MessageSent event to a local listener. Every time that I tried to do php artisan event:generate I would get

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

I finally found that my EventService provider was using

use Illuminate\Support\ServiceProvider;

when I switched this to use

use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;

The event was registered properly! Maybe this will help someone.

Upvotes: 1

Madacol
Madacol

Reputation: 4276

You can pass data from the controller to the mailable, and then from the mailable to the listener

For example I have a model called SendOrder that I use to keep track the status of the email, so I pass this model from the controller to the listener

This is what you have to do from scratch

In your controller

Pass the model to your Mailable constructor

$send_order = SendOrder::create(['status' => 'received', 'email' => '[email protected]']);

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

In the Mailable SendNewMail

Class Mailable has a method withSwiftMessage() which you can use to store variables/objects that you can access later from the listener.

We will make a constructor that pass the model to the build() method where we can execute the withSwiftMessage() to store it for later.

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

     }
}

Create the listener

Register the event and listener in the file app/Providers/EventServiceProvider.php

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

Now execute the command:

php artisan event:generate

This will automatically generate the new listener app\Listeners\LogSentMessage with a template code that's connected to the built-in event Illuminate\Mail\Events\MessageSent

In your Listener LogSentMessage

You can access the model this way:

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

Upvotes: 7

Hariadi
Hariadi

Reputation: 606

Doing php php artisan event:generate will generate App\Listeners\LogSentMessage for you.

Edit the file for example:

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

Upvotes: 1

user2749200
user2749200

Reputation: 59

In your EventServiceProvider add your event and listener

protected $listen = [
       'Illuminate\Notifications\Events\NotificationSent' => [
       'App\Listeners\YourListenerClass',
    ],
]; 

and in YourListnerClass

public function handle(NotificationSent $event)
{

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

}

Upvotes: 2

Related Questions