I have the following error:
Undefined property: Illuminate\Notifications\Events\NotificationSent::$user in /var/www/app/app/Listeners/NoticationListener.php:31
The error occurs here:
<?php
namespace App\Listeners;
use Illuminate\Notifications\Events\NotificationSent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class NoticationListener implements ShouldQueue
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param NotificationSent $event
* @return void
*/
public function handle(NotificationSent $event)
{
$notification = $event->notifiable;
$addressee = $notification; //error here
$address = $notification;
$type = "Notification";
dispatch(new SendEmail($type,$addressee,$address));
}
}
I don't understand this undefined property, especially on this line. How can I dd()
from here? I tried to log the $event
but I couldn't get it to log, only got this error.
My notifications work very well in the application, I just want an email to accompany them, which is why I have this event-listener/job.
Thank you.
EDIT
The repository code that is dispatching the notification is below:
public function notify($asset)
{
$users = User::where("id","!=",Auth::user()->id)->get();
Notification::send($users, new NewAsset($asset));
}
That extension of the Notification
class is below:
class NewAsset extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @return void
*/
protected $asset;
public function __construct($asset)
{
$this->asset = $asset;
}
/**
* 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 [
'asset_id' => $this->asset->id
];
}
}
EDIT 2
If someone could advise how to do some error checking at this juncture, that could be helpful going forward. Because the code is async on the server it isn't returning data to the client, and when I try to get it to Log
it doesn't seem to do so before it gets caught in the error.
How can I go about debugging in this scenario?
I've looked at the framework's source code and have no idea where the $user property is coming from. I assume it has to do with $event->notifiable
being tied to the User
model, but if it fires correctly for all affected users from within the application, why would its property be undefined
in this context?
Please assist, thank you.
This is a strange issue. As you found yourself, Laravel doesn't set a $user
property on that object itself, so something else must be involved. Here's my understanding of the process:
Notification::send()
→ enqueue NewAsset
notification for each user NewAsset
notification → send notifications NotificationSent
event → enqueue NotificationListener
handler Error seems to occur here:
NotificationListener
handler → handle event SendEmail
[→ enqueue if ShouldQueue
] SendEmail
if ShouldQueue
→] Send notification email As you can see, there's a lot of serialization and deserialization going on when enqueueing and dequeueing the jobs for the notification. It seems like the framework is trying to set the $user
property when deserializing the the NotificationSent
event from the queue, but it's hard to tell from your question without a full stack trace, and I'm not sure what adds $user
to the serialized data without more visibility into the code.
Here are some debugging suggestions to try:
Restart the queue worker:
After a queue worker starts, the PHP process doesn't reload changes to the source code from disk if the autoloader already imported the file. It seems possible that someone added the $user
property to an object but didn't restart the worker, so it never picked up the change. During development, we need to restart the queue workers whenever the code changes for a queueable item. When deploying to production, it's a good idea to restart queue workers as part of the deployment process.
Alternatively, use the artisan queue:listen
command instead of queue:work
during development. This mode restarts the entire framework for each job.
Set QUEUE_DRIVER
to sync
:
This prevents the framework's event system from serializing the event data. If the notification email sends without any errors, then we know that custom code somewhere is adding a $user
property to the event.
Check serialized queue data:
It's not clear from the question which queue driver your app uses. If you're not using sync
, we can look at the pending jobs in the queue to try to find the discrepancy (in the database, Redis, etc).
php artisan queue:work --once
to manually process one job until the queued job runs and fires the NotificationSent
event. NotificationSent
event We can also use this approach to dump data using dd()
during queue jobs because artisan queue:work --once
runs in the foreground.
Don't enqueue the NotificationSent
event handler:
Because the notification is already configured to process in a queued background job, we don't necessarily need to enqueue the notification event handler as well. Try removing the ShouldQueue
interface to see if this resolves the problem.
As other commenters mentioned, this problem may be better solved using Laravel's Mail Notifications which remove the need for a separate NotificationSent
event handler entirely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With