How to send notification through only one channel - Laravel 9 - laravel

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)

Related

Laravel: How to properly send notification to multiple users with different url/ in Registration Controller

I am trying to send notifications to the user after registration with the default auth of laravel 6. I tried using the notification facade, but it gives the same URL for all emails. I tried using the ->notify, but it gives me the error. By the way, I am using smtp.office365.com
Expected response code 354 but got code "503", with the message "503 5.5.1 Bad sequence of commands"
RegisterController
$users = User::where('department_id', $data['department'])
->where(function ($query) {
$query->where('manager_level', 'sm1')
->orWhere('manager_level', 'sm2')
->orWhere('department_level', 'dh');
})->get();
foreach ($users as $u) {
$u->notify(new ConfirmUser(($u->department_level == 'dh') ? $u->department_level : $u->manager_level));
}
}
InConfirmUser
protected $level;
/**
* Create a new notification instance.
*/
public function __construct($level)
{
$this->level = $level;
}
/**
* Get the notification's delivery channels.
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject('Confirm User')
->greeting("Dear {$notifiable->name},")
->line('Please click the button below to confirm that the concerned user is your staff')
->action('Confirm User', url('/').$this->level)
->line('If you did not know the concerend staff, no further action is required.');
}
/**
* Get the array representation of the notification.
*/
public function toArray($notifiable)
{
return [
//
];
}
To fix the error message change the value of MAIL_ENCRYPTION to tls in your configuration file and also make sure the MAIL_FROM_ADDRESS is exactly your Office365 email adress.
Tell us more about the ->department property. Isn't it possible that the department can be the same? Or is it null in the mail?
In the code you've wrote $u->deparment without a t. So change it to this:
u->notify(new ConfirmUser($u->department));
This could eventually solve your problem.

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 Notifications - delay email sending and cancel if condition met

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

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'];
}
}

Undefined eager-loaded model in Laravel Echo event

I'm using Laravel Echo to broadcast events from the server to the client.
The application is a forum, where users can create posts in topics.
Here is the controlled method code where the new post is created, and the event dispatched.
$post = Post::create([
'user_id' => 1,
'topic_id' => request('topic_id'),
'body' => request('body'),
]);
// Fetch the post we've just created, with the relationships this time
$post = Post::with('user', 'topic')->find($post->id);
// Broadcast the event
event(new PostCreated($post));
Here is the event class :
class PostCreated implements ShouldBroadcast
{
public $post;
public function __construct(Post $post)
{
$this->post = $post;
}
public function broadcastOn()
{
return new Channel('topics.' . $this->post->topic_id);
}
}
Finally, here is where the event is intercepted in the front-end :
Echo.channel('topics.' + this.topic.id)
.listen('PostCreated', (e) => {
this.posts.push(e.post);
});
The problem is that I can't seem to access the user property from the listen() method on the front-end.
console.log(e.post.user) // Undefined
If I do a console.log() of the post, I can see the properties of the Post (user_id, topic_id, body, created_at, updated_at) but it's not showing the user or topic properties that were eager-loaded in the controller, before the event was sent.
Those properties are accessible from the event class itself :
// In the __construct() method of the PostCreated event
echo $this->post->user->name; // Works, the name is echo'd
... but somehow are not sent to the front-end when the event is broadcasted.
How can I make sure that the user and topic properties are sent to the client, along with the post itself?

Resources