我有以下错误:
未定义的属性: Illuminate \ Notifications \ Events \ NotificationSent :: $ user in /var/www/app/app/Listeners/NoticationListener.php:31
此处发生错误:
<?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));
}
}
我不明白这个未定义的属性,特别是在这一行上。我怎么能dd()
从这里来?我试图记录$event
,但我无法记录,只有这个错误。
我的通知在应用程序中运行良好,我只想要一封电子邮件随附,这就是为什么我有这个事件监听器/工作。
谢谢。
修改
调度通知的存储库代码如下:
public function notify($asset)
{
$users = User::where("id","!=",Auth::user()->id)->get();
Notification::send($users, new NewAsset($asset));
}
Notification
类的扩展名如下:
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
];
}
}
编辑2
如果有人可以建议如何在此时进行错误检查,那么这可能会有所帮助。因为代码在服务器上是异步的,所以它不会将数据返回给客户端,当我尝试将它传递给Log
时,它似乎不会在错误中被捕获之前这样做。
如何在这种情况下进行调试?
我查看了框架的source code,并且不知道$ user属性的来源。我认为它与$event->notifiable
绑定到User
模型有关,但如果它在应用程序中为所有受影响的用户正确触发,为什么在此上下文中它的属性为undefined
?
请帮助,谢谢。
答案 0 :(得分:4)
这是一个奇怪的问题。正如您自己发现的那样,Laravel不会在该对象本身上设置$user
属性,因此必须涉及其他内容。以下是我对该过程的理解:
Notification::send()
→为每个用户排队NewAsset
通知NewAsset
通知→发送通知NotificationSent
event→enqueue NotificationListener
handler 错误似乎发生在这里:
NotificationListener
处理程序→处理事件SendEmail
的调度工作[→ShouldQueue
] SendEmail
→发送通知电子邮件ShouldQueue
的作业排队
醇>
正如您所看到的,当对通知的作业进行入队和出列时,会进行大量的序列化和反序列化。似乎框架在从队列中反序列化$user
事件时尝试设置NotificationSent
属性,但是如果没有完整的堆栈跟踪,很难从您的问题中判断出来,而且我不确定什么将$user
添加到序列化数据而没有更多的代码可见性。
以下是一些尝试的调试建议:
重新启动队列工作程序:
队列工作程序启动后,如果自动装带器已导入文件,则PHP进程不会从磁盘重新加载对源代码的更改。似乎有人将$user
属性添加到对象但没有重新启动工作程序,因此它从未接收到更改。在开发期间,每当代码更改为可队列项时,我们都需要重新启动队列工作程序。部署到生产环境时,最好在部署过程中重新启动队列工作程序。
或者,在开发期间使用artisan queue:listen
命令而不是queue:work
。此模式会为每个作业重新启动整个框架。
将QUEUE_DRIVER
设为sync
:
这可以防止框架的事件系统序列化事件数据。如果通知电子邮件发送没有任何错误,那么我们知道某处的自定义代码正在向事件添加$user
属性。
检查序列化队列数据:
问题不清楚您的应用使用哪个队列驱动程序。如果您不使用sync
,我们可以查看队列中的待处理作业以尝试找出差异(在数据库中,Redis等)。
php artisan queue:work --once
以手动处理一个作业,直到排队的作业运行并触发NotificationSent
事件。 NotificationSent
事件我们还可以使用此方法在队列作业期间使用dd()
转储数据,因为artisan queue:work --once
在前台运行。
不要将NotificationSent
事件处理程序排入队列:
由于通知已配置为在排队的后台作业中处理,因此我们不一定需要将通知事件处理程序排入队列。尝试删除ShouldQueue
界面以查看是否可以解决问题。
正如其他评论者所提到的,使用Laravel的Mail Notifications可以更好地解决这个问题,这样就完全无需单独的NotificationSent
事件处理程序。