本文介绍了Laravel通知侦听器在实现队列时无用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Laravel版本:5.5.*

Laravel Version: 5.5.*

PHP版本:7.1.*

PHP Version: 7.1.*

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

According to the docs 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框架(右上方)中,仅从 sendToNotifiable new Events \ NotificationSent($ notifiable,$ notification,$ channel,$ response)/code>函数,而该函数仅从 sendNow 函数中触发. send 函数本身就是这样的:

Notice that in the framework github (linked right above), that new Events\NotificationSent($notifiable, $notification, $channel, $response) is only fired from the sendToNotifiable function, which in turn is only fired from the sendNow function. The send function itself, is like this:

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 来自该类构造函数的数据.

That is, as it reads to me, the event will not fire if it is a case of if ($notification instanceof ShouldQueue) { as queueNotification never triggers an event listener. I assume it goes into the queue and then will need to re-trigger the event, but I don't think this is happening, because my NotificationSent listener isn't populated with any data from that class constructor.

EventServiceProvider:

EventServiceProvider:

 protected $listen = [
       'Illuminate\Notifications\Events\NotificationSent' => [
        'App\Listeners\NewNotificationListener',
    ],

NewNotificationListener:

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:.

var_dump here is empty, I get nothing in my log, just Notification Listener:.

所以我的问题是,为什么要这样做?如何在需要使用队列的同时使用Notification事件侦听器?是我做错了什么还是框架?

So my question is, why is this and how can I have a Notification event listener while leveraging the Queue as I need to do. Is it something I am doing wrong or is it the framework?

推荐答案

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

我的盒子上的 NotificationSent 在排队和处理时会按预期触发并捕获.

The NotificationSent on my box is triggered and captured as expected when it's being queued and handled.

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

When Laravel hit this piece of code in NotificationSender:

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

它使用队列调度程序将通知排队,并将其存储到您的队列中.当您的工作人员拿起它时,它会反序列化命令,然后启动 SendQueuedNotifications .然后,此类将处理排队的通知,并处理队列():

It queues the notification using the Queue Dispatcher and store it into your queue. And when your worker pick it up, it unserialise the command, and launches SendQueuedNotifications. This class will then handle the queued notifications, and handle the queue (source):

public function handle(ChannelManager $manager)
{
    $manager->sendNow($this->notifiables, $this->notification, $this->channels);
}

然后 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);
}

然后您就去了.调用 NotificationSender 中的 sendNow . NotificationSent 事件应在此函数中调用.

And there you go. The sendNow in NotificationSender is called. The NotificationSent event should be called in this function.

修改

这是我测试的方式:

  1. 确保已正确设置队列.我使用一个数据库队列,与jobs/failed_jobs表组合.

  1. Make sure your queue has been set up correctly. I use a database queue, with 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
            ]
        ];
    }
    

  • 创建虚拟通知(发送Hello电子邮件):

  • Create a dummy notification (send an Hello email):

    <?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队列:工作.

  • Restart your queue worker. I simply restart my php artisan queue:work.

    发送通知

    $user->notify(new WelcomeNotification());
    

  • 检查 laravel.log ,您应该在其中打印 NotificationSent 的类名.

  • Check laravel.log, you should have the class name of NotificationSent printed there.

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

  • 这篇关于Laravel通知侦听器在实现队列时无用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    09-06 03:56