Слушатель уведомлений Laravel бесполезен при реализации очереди

Версия 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);
    }

То есть, как мне кажется, событие не сработает, если оно if ($notification instanceof ShouldQueue) { как queueNotification никогда не запускает прослушиватель событий. Я предполагаю, что это идет в очередь, а затем нужно будет повторно инициировать событие, но я не думаю, что это происходит, потому что мой NotificationSent слушатель не заполнен данными из этого конструктора класса.

EventServiceProvider:

 protected $listen = [
       'Illuminate\Notifications\Events\NotificationSent' => [
        'App\Listeners\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:,

Итак, мой вопрос: почему это так и как я могу иметь прослушиватель событий уведомлений, используя Очередь, как мне нужно. Это я что-то не так делаю или это фреймворк?

1 ответ

Решение

Быстрый ответ: Перезапускали ли вы работника очереди, когда вносили эти изменения?

NotificationSent на моем боксе срабатывает и захватывается, как и ожидалось, когда он ставится в очередь и обрабатывается.


Когда Laravel ударил этот кусок кода в NotificationSender:

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

Он ставит уведомление в очередь с помощью диспетчера очереди и сохраняет его в своей очереди. И когда ваш работник забирает его, он отменяет сериализацию команды и запускает SendQueuedNotifications, Этот класс будет затем обрабатывать уведомления в очереди и обрабатывать очередь ( источник):

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

И вот, пожалуйста. 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. Создайте фиктивное уведомление (отправьте приветственное письмо):

    <?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  
    
Другие вопросы по тегам