Laravel 通知监听器在实现队列时没用

Sum*_*per 2 events laravel laravel-5.5

Laravel 版本:5.5.*

PHP 版本:7.1.*

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

请注意,在 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);
    }
Run Code Online (Sandbox Code Playgroud)

也就是说,它读取对我来说,事件不会火,如果它是的情况下,if ($notification instanceof ShouldQueue) {作为queueNotification从来没有触发事件侦听器。我假设它进入队列,然后需要重新触发事件,但我认为这不会发生,因为我的NotificationSent侦听器没有填充来自该类构造函数的任何数据。

事件服务提供者:

 protected $listen = [
       'Illuminate\Notifications\Events\NotificationSent' => [
        'App\Listeners\NewNotificationListener',
    ],
Run Code Online (Sandbox Code Playgroud)

新通知监听器:

<?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));   
} 
}
Run Code Online (Sandbox Code Playgroud)

var_dump这里是空的,我的日志中什么也没有,只有Notification Listener:.

所以我的问题是,为什么会这样,我如何在需要时利用队列的同时拥有一个通知事件侦听器。是我做错了什么还是框架?

Lio*_*han 5

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

NotificationSent在我的箱子被触发,捕获时,它的排队和处理的预期。


当 Laravel 在 中遇到这段代码时NotificationSender

if ($notification instanceof ShouldQueue) {
    return $this->queueNotification($notifiables, $notification);
}
Run Code Online (Sandbox Code Playgroud)

它使用 Queue Dispatcher 对通知进行排队,并将其存储到您的队列中。当您的工作人员拿起它时,它会反序列化命令,并启动SendQueuedNotifications. 然后这个类将处理排队的通知,并处理队列():

public function handle(ChannelManager $manager)
{
    $manager->sendNow($this->notifiables, $this->notification, $this->channels);
}
Run Code Online (Sandbox Code Playgroud)

ChannelManager做到这一点(来源):

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);
}
Run Code Online (Sandbox Code Playgroud)

你去吧。将sendNowNotificationSender被调用。该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));
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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
            ]
        ];
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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');
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 重新启动您的队列工作器。我只是重新启动我的php artisan queue:work.

  6. 发送通知

    $user->notify(new WelcomeNotification());
    
    Run Code Online (Sandbox Code Playgroud)
  7. 检查laravel.log,您应该在NotificationSent那里打印类名。

    [2018-03-06 09:51:02] production.INFO: Illuminate\Notifications\Events\NotificationSent  
    
    Run Code Online (Sandbox Code Playgroud)