My requirement is to mark the notification read, if a user clicks on the push notification in mobile. But only one notification need to be get updated, so the database notification id need to be passed in push notification. Is there any way to do this?
read_at field is already in Laravel notifications table. That logic is solved by Laravel already and it got methods to query read and unread notifications.
$this->id will contain the notification id. The same id will be inserted in the database if database is given as a channel method. You can push this to push notification through data fields.
I think you can include notification object as json with your push notification so once it's received by web, android or iOS you catch the data and handle it on notification read event
@nsjithinsyam I am facing the same issue. It looks like it's not possible at least not in a nice and clean way. The issue lies with the fact that there is not apparent way to pass the full DatabaseNotification object to the channel for push notification (or anything else for that matter).
A possible (albeit ugly solution) would be to pass some sort of UUID to the Notification (shared by database and push) then do a like to mark the notification read, but it's expensive and not very nice.
@nsjithinsyam this is a possible solution although it might fail due to competing notifications coming in at the same time.
return ['database', PushNotification::class];
(Order does matter, database being first will generate the actual DB notification)
// To mark the notification as read we need the notification id
// There is no clean way to achieve this other than getting the latest notification for the user and hope for the best
// TODO this is clearly a race condition, needs investigation to tighten this up
$DatabaseNotification = $notifiable->notifications->first();
if( $DatabaseNotification ) {
$url = route('user.notification.mark.read', ['notification_id' => $DatabaseNotification->getKey()]);
} else {
$url = $this->link_to;
}
//the way i went about it was this
<?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 myNotification 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','mail',SocketChannel::class];
return $channels;
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$url = url('test-link/?notify_id='.$this->id);
return (new MailMessage)
->subject('Mail Notification')
->greeting('Hello')
->line('Mail Content')
->action('View Details',$url)
->line('concluding message');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toDatabase($notifiable)
{
return [
'url' => url('test-link/?notify_id='.$this->id),
'message' => 'Notification message',
];
}
/**
* Broadcast with redis (My use case tho)
*/
public function toSocket($notifiable)
{
$url = url('test-link/?notify_id='.$this->id);
$data[
'url' => $url,
'content' => ''your content'
]
Redis::publish('push-message:', json_encode(['data'=>$data]));
}
}
<?php
//the custom channel according to the documentation
namespace App\Channels;
use Illuminate\Notifications\Notification;
class SocketChannel
{
/**
* Send the given notification.
*
* @param mixed $notifiable
* @param \Illuminate\Notifications\Notification $notification
* @return void
*/
public function send($notifiable, Notification $notification)
{
$message = $notification->toSocket($notifiable);
// Send notification to the $notifiable instance...
}
}
$(document).ready(function(){
var url = new URL(window.location);
var notify_id = url.searchParams.get("notify_id");
if (notify_id != null) {
var base_url = window.location.protocol+"//"+window.location.host;
var link = base_url+'/notifications/mark-as-read/'+notifyId;
$.ajax({
url: link,
method:'get',
})
.done(function(response){
if (response.status == 'error') {
console.warn('Could not update notifications');
}else{
//handle your success
}
})
.fail(function(jqXHR){
console.warn('Could not update notifications');
})
}
})
Hope it helps. The '$this->id' in the notification class is the generated id that is then saved in the notifications table. For some reasons unknown, the value returns null both in the constructor and the via methods that is why i kept calling it in the different via methods
I found this on Google, and found a decent solution using the NotificationSent event to get the notification id. I have posted the code here: https://stackoverflow.com/a/71648749/1308275