hyphen
hyphen

Reputation: 3450

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:

  1. Fire a database notification.
  2. Listen for a new database notification to be created
  3. 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.

Upvotes: 1

Views: 884

Answers (1)

vens
vens

Reputation: 1

Since I was faced with exactly the same problem, I would like to respond to the question, even though I will probably be late for the party.

Since you are using the database driver for notifications, you can easily implement Eloquent Model Broadcasting functionality.

All changes to the model automatically trigger broadcasts on the selected channel.

Just forget the NotificationCreatedEvent and directly use the BroadcastsEvents trait in the Notification class. There you define in the methods broadcastOn and broadcastAs which channel is addressed.

class Notification extends DatabaseNotification
{
    use HasFactory, BroadcastsEvents;
    
    public function users()
    {
        return $this->belongsTo(User::class, 'notifiable_id');
    }
    
    /**
     * Define the model broadcast events and the broadcast channel name.
     */
    public function broadcastOn(string $event): array
    {
        // only broadcast on 'created' and 'updated' events
        return match ($event) {
            'created', 'updated' => [new PrivateChannel('users.' . $this->notifiable_id);],
            default => []
        };
    }
    
    /**
     * The model event's broadcast name.
     */
    public function broadcastAs(string $event): string|null
    {
        return match ($event) {
            'created' => 'notification-created',
            'updated' => 'notification-updated',
            default => null,
        };
    }
}

Check out the Laravel documentation for more information https://laravel.com/docs/10.x/broadcasting#model-broadcasting

Upvotes: 0

Related Questions