Laravel Notifications - delay email sending and cancel if condition met - laravel

I have an app where I am sending a push notification which is fine if the user is logged into the application - however, if they're not / if they have not read the notification within X minutes I'd like to send them an email.
The way I am going about this is to use Laravel Notifications to create a mail, broadcast & database notification. On the toMail() method I'm returning a mailable with a delay -
public function toMail($notifiable)
{
return (new \App\Mail\Order\NewOrder($this->order))
->delay(now()->addMinutes(10));
}
After the minutes are up, the email will send but, before the send goes ahead I'd like to perform a check to see if the push/database notification has already been marked as read and if it has cancel the email send. The only way I can think to do this is to bind to the MessageSending event that is baked into Laravel -
// listen for emails being sent
'Illuminate\Mail\Events\MessageSending' => [
'App\Listeners\Notification\SendingEmail'
],
The only problem is this listener receives a Swift mail event and not the original mailable I was dispatching so I don't know how to cancel it. Any ideas and thanks in advance?

Class extends Notification
public function via($notifiable)
{
if($this->dontSend($notifiable)) {
return [];
}
return ['mail'];
}
public function dontSend($notifiable)
{
return $this->appointment->status === 'cancelled';
}
Class EventServiceProvider
protected $listen = [
NotificationSending::class => [
NotificationSendingListener::class,
],
];
Class NotificationSendingListener
public function handle(NotificationSending $event)
{
if (method_exists($event->notification, 'dontSend')) {
return !$event->notification->dontSend($event->notifiable);
}
return true;
}
For more details look article Handling delayed notifications in Laravel

Related

How to send notification through only one channel - Laravel 9

I need to send notifications to users using Web Push and e-mail, but in some cases it may turn out that the user does not have an e-mail address, so then only using Web Push.
Is it possible to choose which channel the notification should be sent through, or do I have to create separate notifications for both channels and trigger the e-mail notification only if the user has an assigned address?
Methods in notifications:
public function via($notifiable)
{
return [
MailChannel::class,
WebPushChannel::class,
];
}
public function toWebPush($notifiable, $notification)
{
return (new WebPushMessage)
->title('Twój profil jest aktywny')
->body('Administrator aktywował Twoje konto')
->data([
'type' => class_basename($this),
])
->options(['TTL' => 1000]);
}
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Title..')
->line("Content...")
}
Sending notifications:
$user->notify(new UserActivation());
That's what the via method is for. Check for the $notifiable->email there and return the appropriate channel(s)

Sending Data to Pusher in laravel broadcast

I am having issues with sending data object to pusher, after saving data to db. When I send the request to to db , it saved to db then initialize the event but it does not send with the specified object.
event(new NotifyResponderEvent($emergencyRequest));
Here is my code for the event file
class NotifyResponderEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $emergencyRequest;
public function __construct($emergencyRequest)
{
$this->$emergencyRequest = $emergencyRequest;
}
public function broadcastOn()
{
return new Channel('request');
}
public function broadcastAs()
{
return 'emergencyRequest';
}
public function broadcastWith()
{
return [
'data' => [
$this->emergencyRequest
],
];
}
}
This is what I get in pusher after when the event is fired
{
"emergencyRequest": null
}
Even when I log the data before sending its still giving me the same issue, but it is saving on the db and sending to another api that sends sms and some object data as well.
Regards
Sorted ... Not sure what was the problem, I had to delete node_module folder, remove any pusher related packages and reinstall.

Laravel how to capture event with Server Sent Events

The Laravel SSE(server sent event) is a great solution to push the changes to frontend, however, on the server side, we need to have an efficient way to keep track of the updated record(s) before sending notification to frontend. however, the SSE requires a controller to work with, problem is how can the controller capture the Laravel events?
class HomeController extends Controller
{
public function sse(SSE $sse)
{
// how to add the Laravel event listener here?
return $sse->createResponse();
}
}
Laravel provides with events, listeners, broadcasting and channels to communicate with front end via events. You don't need to do that in controllers. You can define broadcast routes in
routes/channels.php
you can then define events that by default include broadcast method in scaffolding.
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
Bind listeners to event and implement "shouldque" interface to that these run as async jobs. You can also use laravel notifications to provide live notification. laravel broadcasting
If you still want to grab event in controller you can specify in EventServiceProvider as
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
DownloadFile::class => [
CompanyDashboardController::class,
],
];
public function boot()
{
parent::boot();
}
}
your event will look like
class DownloadFile
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $process_id;
public function __construct($process_id)
{
$this->process_id = $file;
}
}
Finally you can grab this event in you controller as like:
class CompanyDashboardController extends Controller
{
public function __construct()
{
//constructor
}
public function handle(DownloadFile $event)
{
if($event->process_id == 1)
{
return "something";
}
}
}
If you meant to some Javascript event instead of Laravel read
Use Server-Sent Events to push messages to browser

Laravel Bulk Send Mail with Notification

I read in laravel documentation :
Once the ShouldQueue interface has been added to your notification, you may send the notification like normal. Laravel will detect the ShouldQueue interface on the class and automatically queue the delivery of the notification:
Because of in notification do automatically queue,
if I use in my controller:
public function store(Request $request)
{
$users = User::all()
Notification::send($users, new MyFirstNotification());
}
and in my notification:
public function toMail($notifiable)
{
return new custome-emailTo("emails.welcome",$notifiable);
}
and in custom-mailTo, (it is a mailable class) :
public function __construct($view2,User $user)
{
$this->user = $user;
$this->view = $view2;
}
public function build()
{
$this->to($this->user->email);
return $this->view('emails.welcome');
}
for me, it work and send to many users,
but my questions are:
As stated in the documentation of Laravel,
1. Do it really do queuing for send notification?
2. Do I need queue in mailable laravel class for send bulk email?

Laravel notification facade check user before sending notification

I have a situation that I am sending a notification to multiple users and in past i have used this code:
foreach ($users as $user) {
$user->notify(new StaffNotify($dirtyAttributes, $user));
}
and I would check inside that notification if a user has a player_id
public function via($notifiable)
{
if ($this->user->player_id) {
return [OneSignalChannel::class, 'mail'];
} else {
return ['mail'];
}
}
(for OneSignal) and if he has I would send a push notification also on their mobile phone.
But with this new code:
\Notification::send($users, new StaffNotify($dirtyAttributes));
It is much better because i have only 1 request on my server instead of 250. I don't know how to check if a user has player_id because this works differently.
Does anyone know how to check the user before sending the notification?
You don't have to pass the user as an argument, you already have it in $notifiable and you can check what ever you want.
public function via($notifiable)
{
if ($notifiable->player_id) {
return [OneSignalChannel::class, 'mail'];
} else {
return ['mail'];
}
}

Resources