实现队列时,Laravel通知监听器无用

时间:2018-03-04 22:57:23

标签: laravel events laravel-5.5

Laravel版本:5.5。*

PHP版本:7.1。*

根据文档https://laravel.com/docs/5.5/notifications,订阅Notification事件应该非常简单。我已按照文档中的步骤操作,但我的通知实现了ShouldQueue,并且它们没有正确填充事件侦听器。我想知道问题似乎是 in the framework code

请注意,在框架github(右上方链接)中,new Events\NotificationSent($notifiable, $notification, $channel, $response)仅从sendToNotifiable函数触发,而sendNow函数仅从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) {

也就是说,正如它向我读到的那样,如果queueNotificationNotificationSent的情况,那么事件将不会触发,因为 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)); } } 侦听器没有填充任何数据来自该类构造函数。

EventServiceProvider:

var_dump

NewNotificationListener:

Notification Listener:

System.ComponentModel.DataAnnotations此处为空,我的日志中没有任何内容,只有Sales

所以我的问题是,为什么这个以及如何在我需要的时候利用Queue时有一个Notification事件监听器。这是我做错了还是框架?

1 个答案:

答案 0 :(得分:2)

快速回答:您在进行这些修改后是否重新启动了队列工作程序?

我的框上的NotificationSent会在排队和处理时按预期触发和捕获。

当Laravel在NotificationSender中点击这段代码时:

if ($notification instanceof ShouldQueue) {
    return $this->queueNotification($notifiables, $notification);
}

它使用Queue Dispatcher对通知进行排队,并将其存储到队列中。当你的工作人员拿起它时,它会对命令进行反序列化,然后启动SendQueuedNotifications。然后,该类将处理排队的通知,并处理队列(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);
}

你去吧。调用sendNow中的NotificationSender。应在此函数中调用NotificationSent事件。

修改

这是我测试它的方式:

  1. 确保您的队列设置正确。我使用数据库队列,使用jobs / failed_jobs表组合。

  2. 创建文件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));
        }
    }
    
  3. 修改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
            ]
        ];
    }
    
  4. 创建虚拟通知(发送Hello电子邮件):

    <?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');
        }
    }
    
  5. 重新启动您的队列工作程序。我只是重新启动php artisan queue:work

  6. 发送通知

    $user->notify(new WelcomeNotification());
    
  7. 检查laravel.log,您应该在那里打印NotificationSent的班级名称。

    [2018-03-06 09:51:02] production.INFO: Illuminate\Notifications\Events\NotificationSent