Laravel 通知侦听器在实现队列时无用
Laravel Notifications Listener Is Useless When Implementing the Queue
Laravel版本:5.5.*
PHP版本:7.1.*
根据文档 https://laravel.com/docs/5.5/notifications it should be super simple to subscribe to Notification events. I've followed the steps in the docs, but my Notifications implement ShouldQueue
and they weren't properly populating the event listener. I'm wonder if the issue seems to be in the framework code.
请注意,在 github 框架(链接在上方)中,new Events\NotificationSent($notifiable, $notification, $channel, $response)
仅从 sendToNotifiable
函数中触发,而后者又仅从 [=17 中触发=] 函数。 send
函数本身是这样的:
public function send($notifiables, $notification)
{
$notifiables = $this->formatNotifiables($notifiables);
if ($notification instanceof ShouldQueue) {
return $this->queueNotification($notifiables, $notification);
}
return $this->sendNow($notifiables, $notification);
}
也就是说,正如它读给我的那样,事件 不会触发 如果它是 if ($notification instanceof ShouldQueue) {
的情况,因为 queueNotification
永远不会触发事件听众。我假设它进入队列然后需要重新触发事件,但我认为这不会发生,因为我的 NotificationSent
侦听器没有填充 any 来自 class 构造函数的数据。
事件服务提供商:
protected $listen = [
'Illuminate\Notifications\Events\NotificationSent' => [
'App\Listeners\NewNotificationListener',
],
新通知监听器:
<?php
namespace App\Listeners;
use Illuminate\Notifications\Events\NotificationSent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Jobs\SendEmailForNotifications;
use Illuminate\Support\Facades\Log;
class NewNotificationListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
public function handle(NotificationSent $event)
{
Log:info('Notification Listener:'.' '.var_dump($event));
SendEmailForNotifications::dispatch($event->notification)->delay(now()->addMinutes(10));
}
}
var_dump
这里是空的,我的日志里什么也没有,只有 Notification Listener:
.
所以我的问题是,为什么会这样,以及如何在需要时利用 Queue 的同时拥有 Notification 事件侦听器。是我做错了什么还是框架?
快速回答:您在进行这些修改后是否重新启动了队列工作器?
我的盒子上的 NotificationSent
在排队和处理时按预期触发和捕获。
当Laravel打到NotificationSender
这段代码时:
if ($notification instanceof ShouldQueue) {
return $this->queueNotification($notifiables, $notification);
}
它使用队列调度程序将通知排队并将其存储到您的队列中。当你的工作人员拿起它时,它反序列化命令,并启动 SendQueuedNotifications
。 class 然后将处理排队的通知,并处理队列 (source):
public function handle(ChannelManager $manager)
{
$manager->sendNow($this->notifiables, $this->notification, $this->channels);
}
ChannelManager
这样做 (source):
public function sendNow($notifiables, $notification, array $channels = null)
{
return (new NotificationSender(
$this, $this->app->make(Bus::class), $this->app->make(Dispatcher::class))
)->sendNow($notifiables, $notification, $channels);
}
好了。 NotificationSender
中的 sendNow
被调用。应在此函数中调用 NotificationSent
事件。
编辑
我是这样测试的:
确保您的队列设置正确。我使用数据库队列,jobs/failed_jobs table combo.
创建文件app/Listeners/TestListener.php
<?php
namespace App\Listeners;
use Illuminate\Notifications\Events\NotificationSent;
class TestListener
{
public function handle(NotificationSent $event)
{
\Log::info(get_class($event));
}
}
编辑app/Providers/EventServiceProvider.php
<?php
namespace App\Providers;
use App\Listeners\TestListener;
use Illuminate\Notifications\Events\NotificationSent;
use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* @var array
*/
protected $listen = [
NotificationSent::class => [
TestListener::class
]
];
}
创建虚拟通知(发送问候电子邮件):
<?php
namespace App\Notifications\Users;
use App\Notifications\Notification;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Channels\MailChannel;
use Illuminate\Notifications\Messages\MailMessage;
class WelcomeNotification extends Notification implements ShouldQueue
{
use Queueable;
public function via($notifiable)
{
return [MailChannel::class];
}
public function toMail($notifiable)
{
return (new MailMessage())
->line('Hello');
}
}
重新启动队列工作器。我只是重新启动 php artisan queue:work
.
发送通知
$user->notify(new WelcomeNotification());
检查 laravel.log
,你应该在那里打印 NotificationSent
的 class 名字。
[2018-03-06 09:51:02] production.INFO: Illuminate\Notifications\Events\NotificationSent
Laravel版本:5.5.*
PHP版本:7.1.*
根据文档 https://laravel.com/docs/5.5/notifications it should be super simple to subscribe to Notification events. I've followed the steps in the docs, but my Notifications implement ShouldQueue
and they weren't properly populating the event listener. I'm wonder if the issue seems to be in the framework code.
请注意,在 github 框架(链接在上方)中,new Events\NotificationSent($notifiable, $notification, $channel, $response)
仅从 sendToNotifiable
函数中触发,而后者又仅从 [=17 中触发=] 函数。 send
函数本身是这样的:
public function send($notifiables, $notification)
{
$notifiables = $this->formatNotifiables($notifiables);
if ($notification instanceof ShouldQueue) {
return $this->queueNotification($notifiables, $notification);
}
return $this->sendNow($notifiables, $notification);
}
也就是说,正如它读给我的那样,事件 不会触发 如果它是 if ($notification instanceof ShouldQueue) {
的情况,因为 queueNotification
永远不会触发事件听众。我假设它进入队列然后需要重新触发事件,但我认为这不会发生,因为我的 NotificationSent
侦听器没有填充 any 来自 class 构造函数的数据。
事件服务提供商:
protected $listen = [
'Illuminate\Notifications\Events\NotificationSent' => [
'App\Listeners\NewNotificationListener',
],
新通知监听器:
<?php
namespace App\Listeners;
use Illuminate\Notifications\Events\NotificationSent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use App\Jobs\SendEmailForNotifications;
use Illuminate\Support\Facades\Log;
class NewNotificationListener
{
/**
* Create the event listener.
*
* @return void
*/
public function __construct()
{
//
}
public function handle(NotificationSent $event)
{
Log:info('Notification Listener:'.' '.var_dump($event));
SendEmailForNotifications::dispatch($event->notification)->delay(now()->addMinutes(10));
}
}
var_dump
这里是空的,我的日志里什么也没有,只有 Notification Listener:
.
所以我的问题是,为什么会这样,以及如何在需要时利用 Queue 的同时拥有 Notification 事件侦听器。是我做错了什么还是框架?
快速回答:您在进行这些修改后是否重新启动了队列工作器?
我的盒子上的 NotificationSent
在排队和处理时按预期触发和捕获。
当Laravel打到NotificationSender
这段代码时:
if ($notification instanceof ShouldQueue) {
return $this->queueNotification($notifiables, $notification);
}
它使用队列调度程序将通知排队并将其存储到您的队列中。当你的工作人员拿起它时,它反序列化命令,并启动 SendQueuedNotifications
。 class 然后将处理排队的通知,并处理队列 (source):
public function handle(ChannelManager $manager)
{
$manager->sendNow($this->notifiables, $this->notification, $this->channels);
}
ChannelManager
这样做 (source):
public function sendNow($notifiables, $notification, array $channels = null)
{
return (new NotificationSender(
$this, $this->app->make(Bus::class), $this->app->make(Dispatcher::class))
)->sendNow($notifiables, $notification, $channels);
}
好了。 NotificationSender
中的 sendNow
被调用。应在此函数中调用 NotificationSent
事件。
编辑
我是这样测试的:
确保您的队列设置正确。我使用数据库队列,jobs/failed_jobs table combo.
创建文件
app/Listeners/TestListener.php
<?php namespace App\Listeners; use Illuminate\Notifications\Events\NotificationSent; class TestListener { public function handle(NotificationSent $event) { \Log::info(get_class($event)); } }
编辑
app/Providers/EventServiceProvider.php
<?php namespace App\Providers; use App\Listeners\TestListener; use Illuminate\Notifications\Events\NotificationSent; use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider; class EventServiceProvider extends ServiceProvider { /** * The event listener mappings for the application. * * @var array */ protected $listen = [ NotificationSent::class => [ TestListener::class ] ]; }
创建虚拟通知(发送问候电子邮件):
<?php namespace App\Notifications\Users; use App\Notifications\Notification; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Notifications\Channels\MailChannel; use Illuminate\Notifications\Messages\MailMessage; class WelcomeNotification extends Notification implements ShouldQueue { use Queueable; public function via($notifiable) { return [MailChannel::class]; } public function toMail($notifiable) { return (new MailMessage()) ->line('Hello'); } }
重新启动队列工作器。我只是重新启动
php artisan queue:work
.发送通知
$user->notify(new WelcomeNotification());
检查
laravel.log
,你应该在那里打印NotificationSent
的 class 名字。[2018-03-06 09:51:02] production.INFO: Illuminate\Notifications\Events\NotificationSent