I have created a test event under \app\Events\TestEventTriggered.php :
<?php
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class TestEventTriggered extends Event
{
use SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct()
{ }
/**
* Get the channels the event should be broadcast on.
*
* #return array
*/
public function broadcastOn()
{
return [];
}
}
And an event listener under app\Listeners\ListenToMyEvent.php :
<?php
namespace App\Listeners\Events;
use App\Events\TestEventTriggered;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldBeQueued;
class ListenToMyEvent implements ShouldBeQueued
{
use InteractsWithQueue;
/**
* Create the event handler.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param TestEventTriggered $event
* #return void
*/
public function handle(TestEventTriggered $event)
{
// do some stuff
}
}
In app\Providers\EventServiceProvider.php :
protected $listen = [
'App\Events\TestEventTriggered' => [
'App\Listeners\ListenToMyEvent'
]
];
I then trigger the event for example inside my model's save method :
\Event::fire(new \App\Events\TestEventTriggered);
When i save my model now the event is processed synchronously. So the event's handle method is not processed by the queue.
The docs say to implement the ShouldBeQueued contract in the listener, which is the case in my listener. However, how am i supposed to actually push the event's handle method to the queue? What steps am i missing here? Where do i declare to which queue/tube the event should be pushed?
I am using Amazon SQS to handle my queues.
The laravel docs are a bit confusing about this matter...
Any help is appreciated.
The solution is to add a queue method in which you can set the specific tube the event should be sent to :
public function queue($queue, $command)
{
$queue->pushOn('your_queue_name',$command);
}
Related
I try to import a file with Laravel Command. The import works well. After the import, Laravel triggers an event. This works also well.
With a listener, I catch the event. It works well when I do as example dd('it works')!
<?php
namespace App\Listeners;
use App\EventsNew\Notifiables\ConsignmentCreatedViaApi;
class ConsignmentCreatedListener
{
public function __construct()
{
}
public function handle($event)
{
dd('it works');
}
}
But if I try to save some values into the db, it doesn't work, neighter it returns an error:
<?php
namespace App\Listeners;
use App\Models\Settlement;
class ConsignmentCreatedListener
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
}
/**
* Handle the event.
*
* #param object $event
* #return void
*/
public function handle( $event)
{
Settlement::create([
'consignment_id'=> 1
]);
}
}
I tried to execute Settlement::create in the console command and it works.
Isn't it possible to insert something into the db after an avent? Or is there another way to do it?
I'm able to broadcast a notification to Pusher, but I'm unable to receive the response back in my livewire component.
Here is my Notification class:
<?php
namespace App\Notifications;
use App\Models\Statement;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class StatementCompletedNotification extends Notification implements ShouldQueue, ShouldBroadcast
{
use Queueable;
public $statement;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct(Statement $statement)
{
$this->statement = $statement;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
return ['database', 'broadcast'];
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->statement->uploadedBy->id,
'statement_id' => $this->statement->id,
'file_name' => $this->statement->original_file_name
];
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('users.' . $this->statement->uploadedBy->id);
}
}
And here is the getListeners() method on my Livewire component. I've tried several different things here, first off I tried the way it's shown in the docs, just by referencing my StatementCompletedNotification in the listener, like so:
public function getListeners()
{
return [
"echo-private:users.{$this->user->id},StatementCompletedNotification" => 'refreshNotifications'
];
}
I noticed that in pusher, my event type is listed as Illuminate\Notifications\Events\BroadcastNotificationCreated, and I found this post online, so I tried that method like so:
public function getListeners()
{
return [
"echo-private:users.{$this->user->id},.Illuminate\\Notifications\\Events\\BroadcastNotificationCreated" => 'refreshNotifications'
];
}
Neither way has worked for me.
Here's where I'm attempting to just get something back in my javascript on the client-side:
Echo.private('users.1')
.notification((notification) => {
console.log(notification);
});
I don't get any response and I have no idea what the problem is. I've spent an insane amount of time on this and can't seem to figure it out.
Also, it appears that my notification is being picked up multiple times in the queue:
A little more background, the flow that I have set up right now is basically:
StatementCompleted event gets fired (not queued), there's a listener that handles the StatementCompleted event which is queued, and calls my StatementCompletedNotification class like so:
public function handle($event)
{
$event->statement->uploadedBy->notify(new StatementCompletedNotification($event->statement));
}
I use database notifications, in notification code I have method toDatabase:
public function toDatabase($notifiable)
{
$user = \App\SomeUsers::where('id', $notifiable->id)->first();
return [
'message' => $message,
];
}
it returns data array which is being sent to database channel mentioned in via method of current notification:
public function via($notifiable)
{
return ['database'];
}
Everything is as usual, BUT... The problem is I need id of notification in database here in current notification file so that I could broadcast message (from current notification file) to frontend which contains id of notificaion in db (so I could somehow identify it to mark as read). How to get it?
P.S. Moreover, database notification may be queueable, so... it seems that I can't get id...
P.P.S Another words I need broadcast message which contains ["id" => "id of just added corresponding database notification"].
<?php
namespace App\Notifications;
use App\Channels\SocketChannel;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Redis;
class MyCustomNotification extends Notification implements ShouldQueue
{
use Queueable;
/**
* Create a new notification instance.
*
* #return void
*/
public function __construct($param)
{
$this->param = $param;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via($notifiable)
{
$channels = ['database'];
return $channels;
}
/**
* Get the mail representation of the notification.
*
* #param mixed $notifiable
* #return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
}
/**
* Get the array representation of the notification.
*
* #param mixed $notifiable
* #return array
*/
public function toDatabase($notifiable)
{
info("This is the current notification ID, it's generated right here before inserting to database");
info($this->id);
return [
'id' => **$this->id**,
'message' => 'Notification message',
];
}
}
$this->id solves the problem.
https://laracasts.com/discuss/channels/laravel/get-database-notification-id-in-push-notification
P.S. I want to draw attention to one fact. When I posted this question, I knew about $this->id, but I couldn't make it work. The reason was: when I dive deeper to my target code from the top level I made changes to code, but they didn't apply. The reason is queues. You need to restart laravel worker to apply settings as Laravel caches logic or you need temporarily delete those: implements ShouldQueue and use Queueable.
In order to retrieve the actual ID of the notifications table in Laravel, you need to cast the ID column to string. First, you need to create a new model called, Notification.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Notification extends Model
{
/**
* Cast variables to specified data types
*
* #var array
*/
protected $casts = [
'data' => 'array',
'id' => 'string'
];
}
This way, if you retrieve the model, it will give you the actual ID of the table.
{
"id": "212829d6-5579-449f-a8e5-e86f0a08e0f9",
"type": "App\\Notifications\\CronFailureNotification",
....
}
The accepted answer did not provide a solution for me in Laravel 8. To properly get the id of the notification, listen for the NotificationSent event and retrieve the id there. Example code:
EventServiceProvider.php
protected $listen = [
NotificationSent::class => [
DispatchBroadcastNotification::class
]
];
DispatchBroadcastNotification.php
<?php
namespace App\Listeners;
use App\Notifications\BroadcastNotification;
use Illuminate\Notifications\Events\NotificationSent;
class DispatchBroadcastNotification
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param NotificationSent $event
* #return void
*/
public function handle(NotificationSent $event)
{
$event->notifiable->notify(
new BroadcastNotification($event->notification->id)
);
}
}
BroadcastNotification.php
<?php
namespace App\Notifications;
use App\Models\Tenant\User;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Notifications\Messages\BroadcastMessage;
use Illuminate\Notifications\Notification;
class BroadcastNotification extends Notification implements ShouldBroadcast
{
public $notificationId;
public function __construct($notificationId)
{
$this->notificationId = $notificationId;
}
/**
* Get the notification's delivery channels.
*
* #param mixed $notifiable
* #return array
*/
public function via(User $notifiable): array
{
return ['broadcast'];
}
public function toBroadcast(User $notifiable)
{
return new BroadcastMessage([
'notificationId' => $this->notificationId
]);
}
}
I'm trying to find out how I could access the logged in users ID in the handle method of the listener.
This is how the listener looks like:
namespace App\Listeners;
use App\Events\ProjectWasDeleted;
class DeleteUserProjectMapping
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param ProjectWasDeleted $event
* #return void
*/
public function handle(ProjectWasDeleted $event)
{
$project = $event->project->toArray();
var_dump($project['id']); // This is working.
}
}
This is how the event:
namespace App\Events;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
class ProjectWasDeleted
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $project;
/**
* Create a new event instance.
*
* #param $project
*/
public function __construct($project)
{
$this->project = $project;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
The user id is necessary as I would like to delete in a pivot table a record that requires the user id & the project id.
You can access current user instance globally with:
auth()->user()
And get ID with:
auth()->id()
Or:
auth()->user()->id
I've tried to broadcast event with pusher. But after a long hours of debugging I am still without a working solution.
Pusher works great, it's getting events from the debug console. Laravel is also firing the event. I also set up the queue and broadcasting configuration, but I noticed that my queue listener never getting any response.
This is my event listener:
<?php
namespace App\Listeners;
use App\Events\SomeEvent;
use Illuminate\Contracts\Queue\ShouldQueue;
class EventListener implements ShouldQueue
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
}
/**
* Handle the event.
*
* #param SomeEvent $event
* #return void
*/
public function handle(SomeEvent $event)
{
//dd($event);
}
}
Routes:
Route::get('event', function () {
event(new App\Events\SomeEvent());
return "event fired";
});
Event file:
<?php
namespace App\Events;
use App\Events\Event;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class SomeEvent extends Event implements ShouldBroadcast
{
use SerializesModels;
public $data;
public $x = 1111;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct()
{
$this->data = array(
'power'=> '10'
);
}
/**
* Get the channels the event should be broadcast on.
*
* #return array
*/
public function broadcastOn()
{
return ['test_channel'];
}
}
Edit:
i reinstalled laravel and now the queue seems to respond and create row in the job table. but the pusher still dont recive any events from laravel.
Your App\Providers\EventServiceProvider needs to be made aware of the events and listeners.
protected $listen = [
App\Events\SomeEvent::class => [
App\Listeners\SomeListener::class,
],
];
These can be automatically populated by running php artisan event:generate.