Слушатель уведомлений 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
событие должно быть вызвано в этой функции.
редактировать
Вот как я это проверил:
Убедитесь, что ваша очередь была настроена правильно. Я использую очередь базы данных с комбинированной таблицей jobs/failed_jobs.
Создать файл
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
там напечатано.[2018-03-06 09:51:02] production.INFO: Illuminate\Notifications\Events\NotificationSent