I have an application that sends notifications to admins on some user's actions. some admins should notify by SMS and others just via database.
what is the best way to do this? use two notifications or just one? I didn't found any way to change notifiables by their notify method in a notification.
Is there any suggestion?
it can work with If Statement
class yourNotifName extends Notification
{
use Queueable;
private $role;
private $notif;
public function __construct(User $user)
{
$this->role= $user->role;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
if($this->role == "admins") {
$this->notif = ['sms'];
} else {
$this->notif = ['database'];
}
return $this->notif;
}
}
Related
This is related to an earlier question I asked: Am I overcomplicating events/listeners/notifications?.
Based on the feedback received on that question, I modified my approach to attempt to do the following:
Fire a database notification.
Listen for a new database notification to be created
Fire an event and broadcast that to pusher.
So first I send the database notification:
Notification::send($this->requestedBy, new SendMonthlySummaryCreatedNotification($fileDownloadUrl, $fileName));
That notification class looks like this:
class SendMonthlySummaryCreatedNotification extends Notification implements ShouldQueue
{
use Queueable;
public $fileDownloadUrl;
public $fileName;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($fileDownloadUrl, $fileName)
{
$this->fileDownloadUrl = $fileDownloadUrl;
$this->fileName = $fileName;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['database'];
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
'title' => 'Monthly Summary Complete',
'message' => "{$this->fileName} is ready. ",
'link' => $this->fileDownloadUrl,
'link_text' => 'Click here to download',
'show_toast' => true,
'user_id' => $notifiable->id
];
}
}
I found this example of how to add a $dispatchesEvents property to a model in the docs, which I modified to apply it to a new model I created that extends the DatabaseNotification class, which I learned about on this SO question.
class Notification extends DatabaseNotification
{
use HasFactory;
protected $dispatchesEvents = [
'created' => NotificationCreatedEvent::class
];
public function users()
{
return $this->belongsTo(User::class, 'notifiable_id');
}
}
Theoretically the above should dispatch an event when my notification is sent, and then I have the NotificationCreatedEvent that I'd like to use to broadcast to pusher:
class NotificationCreatedEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
protected $notification;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Notification $notification)
{
$this->notification = $notification;
Log::debug($this->notification);
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('users.' . $this->notification->notifiable_id);
}
}
The problem is that everything is working up until the NotificationCreatedEvent It doesn't seem to be getting fired. I don't know if I need to do anything in addition to mapping it in my new Notification model, or if it should just work.
My goal is to add a database notification, and then whenever that happens to send it to pusher so I can notify the user in real-time. This seems like it should work, but I'm not seeing anything coming over in pusher.
When I do this, the user receives email without error:
Notification::send($user, new TicketNotification($details));
But, when I do this, the user also receives an email, but with an error in the screenshot below
Notification::route('mail', 'email_of_non-db_user')->notify(new TicketNotification($details));
Error: Call to a member function create() on null
Do have any idea why? How can I avoid this error?
I have to use On Demand Notification because I need to send a notification to someone who is not stored as a "user".
i think try this one
in TicketNotification update via method with this for only send to mail.
But u r also saved notification into database..
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail'];
}
Thanks Jignesh, your answer works.
Sorry Thamer, I should have posted the whole code from the beginning.
Before, it was :
return ['mail','database'];
Now only :
return ['mail'];
Then, there is no error anymore.
Here my TicketNotification that made the error:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class TicketNotification extends Notification
{
use Queueable;
private $details;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($details)
{
$this->details = $details;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['mail','database'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->subject($this->details['subject'])
->greeting($this->details['title'])
->line($this->details['body'])
->line($this->details['links'])
;
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toDatabase($notifiable)
{
return [
'order_id' => $this->details['order_id']
];
}
}
Add this to your via method to use the same Notification for all your issues:
public function via($notifiable)
{
$availableChannels = [
'mail' => 'mail',
'database' => 'database',
'slack' => 'slack',
'telegram' => TelegramChannel::class
];
$channels = [];
foreach ($availableChannels AS $channel => $driver) {
if ($notifiable->routeNotificationFor($channel)) {
$channels[] = $driver;
}
}
return $channels;
}
You can now use On-Demand Notifications or fire the notificaton on users, without having to make multiple Notifications for each Channel or ON-DEMANDS etc...
I have a receiveEmail boolean field in the User model of a Laravel application. How do I ensure that mail notifications respect this field, and only sends the email to the user if the field is true?
What I want is that this code:
$event = new SomeEvent($somedata);
Auth::user()->notify($event);
where SomeEvent is a class that extends Notification and implements 'mail' on the via() method, only sends an email if the user has allowed emails.
Have any one checked this via() method:
https://laravel.com/docs/6.x/notifications#specifying-delivery-channels
public function via($notifiable)
{
// $notifiable object is User instance for most cases
$wantsEmail = $notifiable->settings['wants_email']; // your own logic
if(!$wantsEmail){
// no email only database log
return ['database'];
}
return ['database', 'mail'];
}
I hope this will work while sending notifications to multiple users too. Thanks
I ended up creating a new Channel that implements the checking. In app/channels, add your channel, something like this:
namespace App\Channels;
use App\User;
use Illuminate\Notifications\Channels\MailChannel;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Arr;
class UserCheckMailChannel extends MailChannel
{
/**
* Send the given notification.
*
* #param mixed $notifiable
* #param \Illuminate\Notifications\Notification $notification
* #return void
*/
public function send($notifiable, Notification $notification)
{
// check if user should receive emails. Do whatever check you need here.
if ($notifiable instanceof User && !$notifiable->receiveEmails) {
return;
}
// yes, convert to mail and send it
$message = $notification->toMail($notifiable);
if (!$message) {
return;
}
parent::send($notifiable, $notification);
}
}
Then bind your class on Providers/AppServiceProvider.php to the old mail class:
/**
* Register any application services.
*
* #return void
*/
public function register()
$this->app->bind(
\Illuminate\Notifications\Channels\MailChannel::class,
UserCheckMailChannel::class
);
}
try to create new method in user model like this..
user model file..
public function scopeNotifyMail() {
if($this->receiveEmail == true) { //if field is enable email other wise not send..
$event = new SomeEvent($somedata);
$this->notify($event);
}
}
and now call like this in controller..
Auth::user()->notifyMail();
or
App\User::find(1)->notifyMail();
or
App\User::where('id',1)->first()->notifyMail();
im trying to send some values from a DB with Notify to Slack. Somehow every time I load my Website the only message I get is "Array" and not the data from the DB.
This is my Notifications .php
class InventoryReStock extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($reorder)
{
$this->reorder = $reorder;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['slack'];
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toSlack($notifiable)
{
return (new SlackMessage)
->content([$this->reorder]);
}
This is the function that Im using on my controller to get the data form the Db
public function index()
{
//shows all the products in the database in an overview
$products = Product::all()->toArray();
$reord = Product::select('Product_Name')->where('Number_Runs', '<=', '5')->get();
$reorder = json_decode(json_encode($reord), true);
Notification::route('slack', 'https://hooks.slack.com/services/..../...../......')->notify(new InventoryReStock($reorder));
return view('products.lab_inventory_overview', compact('products', 'reorder'));
}
and this is my User.php
public function routeNotificationForSlack($notification)
{
Return 'https://hooks.slack.com/services/..../...../......';
}
Never mind, I found a solution . Just converting the array to string makes it work.
$reorder = implode(', ', array_flatten($reorde));
I am new in Laravel and I am trying to send Slack Notification each time an order is placed. For testing, I used my Incoming Webhook. Now when I am changing the webhook to clients slack webhook. Its still sending the notification to old webhook.
Can you help me sort this out?
This is my Listener
public function handle(OrderConfirmed $event)
{
$admin=User::find(73);
$user=User::find($event->order->user_id);
$order=Order::find($event->order->id);
Notification::send(User::find(73),(new \App\Notifications\PaymentProcessedNot($user,$order)));
}
This is my PaymentProcessedNot class
class PaymentProcessedNot extends Notification implements ShouldQueue
{
use Queueable;
public $user;
public $order;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(\App\User $user,\App\Order $order)
{
$this->user=$user;
$this->order=$order;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['slack'];
}
public function toSlack($notifiable){
return (new SlackMessage)
->success()
->content('A new Payment was just processed.')
->attachment(function ($attachment){
$attachment->title('Order : '. $this->order->order_id)
->fields([
'Amount' => ' ₹'. number_format($this->order->amount,2),
'From' => $this->user->name,
'Payment Mode' => strtoupper($this->order->payment_mode)
]);
});
}
}
This is my User.php
public function routeNotificationForSlack()
{
return 'new_slack_incoming_webhook';
}
If your using .env you should clear the cache!
Just checking this is actually the url right?
return 'new_slack_incoming_webhook';