Reputation: 345
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
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
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
Pass the model to your Mailable constructor
$send_order = SendOrder::create(['status' => 'received', 'email' => '[email protected]']);
Mail::to($receiverAddress)->send(new SendNewMail($send_order));
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
}
}
protected $listen =
'Illuminate\Mail\Events\MessageSent' => [
'App\Listeners\LogSentMessage',
],
];
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
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
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
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