Database listening with Laravel Websocket - laravel

I have done every installation related to Laravel Websocket. Here's what I'm trying to do: I have a table in the database where I keep my orders. When a new order arrives, I want to print it to the console on my home page blade.
I would be glad if you help. Thanks.

You can use model event like below, in your Order model
protected static function booted()
{
//everytime when new order is created this function will be called
static::created(function ($order) {
//then broadcast event
NewOrder::dispatch($order);
});
}
Then you have to define channel in youre route/channel.php
use App\Models\Order;
Broadcast::channel('newOrder', function ($user) {
return $user->id;
});
Then create event php artisan make:event NewOrder
class NewOrder implements ShouldBroadcast
{
/**
* The user that created the server.
*
* #var \App\Models\User
*/
public $user;
/**
* Create a new event instance.
*
* #param \App\Models\User $user
* #return void
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('newOrder');
}
}
then listen for NewOrder event in newOrder Channel
Echo.channel(`newOrder`)
.listen('NewOrder', (e) => {
console.log(e.order);
});
Read Documentation more info https://laravel.com/docs/9.x/broadcasting#pusher-channels

Related

Broadcast event to Pusher when database notification is created

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.

how to send notification from admin to user by id with Laravel Pusher

I have successfully implemented pusher on my laravel app but I want to make, when the user succeeds in making an order the default status_message for the order is pending, the case is when the admin changes the status_message to processed, the user who has ordered gets a notification that the order he has made is processed.
this is my code but this code sends notifications to all users.
Controller
if ($data->status_message == 'processed') {
event(new OrderEvent('Hi, Your order is processed!'));
//...
}
My Event OrderEvent.php
public function broadcastOn()
{
return new Channel('notif-channel');
}
/**
* Broadcast order event.
*
* #return void
*/
public function broadcastAs()
{
return 'order-event';
}
in App blade
var channel = pusher.subscribe('notif-channel');
channel.bind('order-event', function(data) {
const obj = JSON.parse(JSON.stringify(data));
const message = obj.message;
blah blah blah
}
Both user and admin should be on the same channel. For example if user is subscribed for channel 'order-channel-SetUserID'.
Admin should send the message to that channel and you should look for it on the front end and make the changes on the DOM.
In your controller when you submit the changes of the status of the order run the event with the channel name
event(new OrderEvent($user_id, 'Hi, Your order is processed!'));
Now your event should look similar to this:
class OrderEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $user_id;
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($user_id, $message)
{
$this->user_id = $user_id;
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('order-channel.' . $this->user_id);
}
public function broadcastAs()
{
return 'order-event';
}
}
Of course you can change your class Name etc... I'm just giving an idea.
it's important to send the changes on the same channel with this user or else you will make changes to other users that are visiting your website.
EDITED
Here is what else you need to configure.
In app/Providers/EventServiceProvider.php
You need to put the event in protected $listen
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
OrderEvent::class => [
OrderEventListener::class,
],
];
In app/Listeners You should create OrderEventListener.php and set it up as follow:
<?php
namespace App\Listeners;
use App\Events\OrderEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Pusher;
class OrderEventListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param \App\Events\OrderEvent $event
* #return void
*/
public function handle(OrderEvent $event)
{
$pusher = new Pusher(env('PUSHER_APP_KEY'),
env('PUSHER_APP_SECRET'), env('PUSHER_APP_ID'), [
'cluster' => env('PUSHER_APP_CLUSTER'),
'useTLS' => true
]);
$pusher->trigger($event->broadcastOn(),
$event->broadcastAs(), $event->data);
}
}
check your Debug Console in pusher dashboard? If you can see the event firing there all you need to do is show the message with javascript. If no event is running then something in your code is missing.

Eloquent event deleting listener return false will stop delete function? [laravel]

I have Team eloquent and TeamObserver. TeamObserver has deleting event and in the event i call TeamDeletingEvent. TeamDeletingEvent dispatch TeamDeletingListener. If TeamDeletingLister will return false will stop the team delete function?
TeamObserver
class TeamObserver
{
/**
* Handle the team "deleting" event.
*
* #param Team $team
* #return void
*/
public function deleting(Team $team)
{
event(new TeamDeletingEvent($team));
}
}
TeamDeletingEvent
class TeamDeletingEvent
{
use SerializesModels;
/**
* #var Team
*/
public $team;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Team $team)
{
$this->team = $team;
}
}
TeamDeletingListener
class TeamDeletingListener
{
/**
* Handle the event.
*
* #param TeamDeletingEvent $event
* #return bool
*/
public function handle(TeamDeletingEvent $event)
{
$teamUser = Team::where('id', $event->team->id)->users()->first();
if(is_null($teamUser)){
return true;
}
return false;
}
}
More than this TeamObserver registered in AppServiceProvider and Event and Listener registered in EventServiceProvider
listener return false will not stop the delete function. It will stop the continuous listener call of the event. But Eloquent event returning false will stop the delete function. (model instance values gets updated but these are not updated in database). More info Detail Answer

Laravel mass update , still fire event

As stated in the doc, laravel will not fire an event on mass update/insert/delete.
https://laravel.com/docs/5.8/eloquent#events
It uses the Builder for this and will not fire an event.
Is there a way that I can still fire an event after a mass update for example? I would only need the query Builder to extract the needed info myself ( log purposes).
It is actually possible , but you have to extend the Eloquent builder ,overwrite the update/insert methods and send the event there.
Just been playing around with it... Needs work, but the basic idea is the following :
class Test extends Model
{
protected $guarded = [];
public $dispatchesEvents = [
'saved' => SavedTest::class
];
/**
* INCLUDE this as a trait in your model.
* Overwrite the eloquentBuilder.
*
* #param \Illuminate\Database\Query\Builder $query
* #return \Illuminate\Database\Eloquent\Builder|static
*/
public function newEloquentBuilder($query)
{
return new TestBuilder($query);
}
}
Extend the eloquent builder...
class TestBuilder extends Builder
{
/**
* Update a record in the database and fire event.
*
* #param array $values
* #return int
*/
public function update(array $values)
{
// normal eloquent behavior.
$result =$this->toBase()->update($this->addUpdatedAtColumn($values));
/*
* Fire event.
*/
if($result){
if( $event = Arr::get($this->model->dispatchesEvents,'saved')){
// at the attributes.
$this->model->fill($this->addUpdatedAtColumn($values));
$queryBuilder =$this->toBase();
event(new $event($this->model,$queryBuilder));
}
}
}
public function insert(array $values)
{
// same idea..
}
}
The event class :
class SavedTest
{
use SerializesModels;
public $model;
public $query;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($model,$query =null)
{
$this->model = $model;
$this->query = $query;
}
}
The listener.
class SavedTestEvent
{
/**
* Create the event listener.
*
*
*/
public function __construct()
{
}
/**
* Handle the event.
*
* #param object $event
* #return void
*/
public function handle($event)
{
// The model , with the attributes.
dump($event->model);
// the query builder , you could extract the wheres or whatever to build your own log for it.
dump($event->query);
}
}
#Paolo on batch request it would not be file the event you must have to perform operation on single record.. like
Analytic::where('id', '>', 100)->get()->each(function($analytic) {
$analytic->delete();
});

Weird Issue with Laravel Slack Notification

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

Resources