Прослушиватель событий Уведомлений Laravel Неопределенное свойство


У меня следующая ошибка:

Неопределенное свойство: Осветить\Уведомления\События\Отправку уведомлений::$пользователь в /var/www/приложение/приложение/Слушатели/noticationlistener.php:31

Ошибка возникает здесь:

<?php

namespace App\Listeners;

use Illuminate\Notifications\Events\NotificationSent;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class NoticationListener implements ShouldQueue
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  NotificationSent  $event
     * @return void
     */
    public function handle(NotificationSent $event)
    {
       $notification = $event->notifiable;
       $addressee = $notification; //error here
       $address = $notification; 
       $type = "Notification";
       dispatch(new SendEmail($type,$addressee,$address));
    }
}

Я не понимаю этого неопределенного свойства, особенно в этой строке. Как я могу dd() отсюда? Я попытался зарегистрировать $event, но не смог его зарегистрировать, только получил эту ошибку.

Мои уведомления очень хорошо работают в приложение, я просто хочу, чтобы их сопровождало электронное письмо, вот почему у меня есть это событие-слушатель/задание.

Спасибо.

РЕДАКТИРОВАТЬ

Код репозитория, отправляющий уведомление, приведен ниже:

public function notify($asset)
{
    $users = User::where("id","!=",Auth::user()->id)->get();
    Notification::send($users, new NewAsset($asset));
}

Это расширение класса Notification приведено ниже:

class NewAsset extends Notification
{
    use Queueable;

    /**
     * Create a new notification instance.
     *
     * @return void
     */
    protected $asset;

    public function __construct($asset)
    {
        $this->asset = $asset;
    }

    /**
     * Get the notification's delivery channels.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function via($notifiable)
    {
        return ['database'];
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            'asset_id' => $this->asset->id
        ];
    }
}

РЕДАКТИРОВАТЬ 2

Если бы кто-нибудь мог посоветовать, как выполнить некоторую проверку ошибок на данном этапе, это могло бы быть полезно в будущем. Потому что код асинхронен на сервере он не возвращает данные клиенту, и когда я пытаюсь передать их Log, кажется, что он не делает этого до того, как попадет в ошибку.

Как я могу приступить к отладке в этом сценарии?

Я просмотрел исходный код фреймворка и понятия не имею, откуда берется свойство $user. Я предполагаю, что это связано с тем, что $event->notifiable привязан к модели User, но если он срабатывает правильно для всех затронутых пользователей из приложения, почему его свойство должно быть undefined в этот контекст?

Пожалуйста, помогите, спасибо.

Author: Cy Rossignol, 2017-09-17

1 answers

Это странная проблема. Как вы обнаружили, Laravel не устанавливает свойство $user для самого этого объекта, поэтому должно быть задействовано что-то еще. Вот мое понимание этого процесса:

  1. Notification::send() → поставить в очередь NewAsset уведомление для каждого пользователя
  2. Удаление из очереди внутреннего задания для NewAsset уведомления → отправка уведомлений
  3. Пожар NotificationSent событие → постановка в очередь NotificationListener обработчик

Похоже, здесь произошла ошибка:

  1. Удаление из очереди внутреннего задания для NotificationListener обработчика → события обработки
  2. Задание отправки для SendEmail [→поставить в очередь, если ShouldQueue]
  3. [Удалить задание из очереди для SendEmail, если ShouldQueue →] Отправить уведомление по электронной почте

Как вы можете видеть, при постановке в очередь и удалении заданий для уведомление. Похоже, что фреймворк пытается установить свойство $user при десериализации события NotificationSent из очереди, но по вашему вопросу трудно судить без полной трассировки стека, и я не уверен, что добавляет $user к сериализованным данным без большей видимости в коде.

Вот несколько предложений по отладке, которые можно попробовать:

Перезапустите работника очереди:

После запуска работника очереди PHP процесс не загружает изменения в исходный код с диска, если загрузчик уже импортировал файл. Кажется возможным, что кто-то добавил свойство $user к объекту, но не перезапустил работника, поэтому он так и не принял изменения. Во время разработки нам необходимо перезапускать работников очереди всякий раз, когда изменяется код для элемента, подлежащего очереди. При развертывании в рабочей среде рекомендуется перезапустить работников очереди как часть процесса развертывания.

В качестве альтернативы используйте artisan queue:listen команда вместо queue:work во время разработки. Этот режим перезапускает всю платформу для каждого задания.

Установите QUEUE_DRIVER в sync:

Это предотвращает сериализацию данных событий в системе событий фреймворка. Если уведомление по электронной почте отправляется без каких-либо ошибок, то мы знаем, что где-то пользовательский код добавляет свойство $user к событию.

Проверка сериализованной очереди данные:

Из вопроса неясно, какой драйвер очереди использует ваше приложение. Если вы не используете sync, Мы можем просмотреть отложенные задания в очереди, чтобы попытаться найти несоответствие (в базе данных, Redis и т. Д.).

  1. Остановите всех работников очереди.
  2. Запустите уведомление через приложение.
  3. Запустите php artisan queue:work --once, чтобы вручную обработать одно задание, пока задание в очереди не запустится и не вызовет событие NotificationSent.
  4. Проверьте задание, созданное в очереди, чтобы обработать событие NotificationSent

Мы также можем использовать этот подход для сброса данных с помощью dd() во время заданий очереди, потому что artisan queue:work --once выполняется на переднем плане.

Не ставьте в очередь обработчик событий NotificationSent:

Поскольку уведомление уже настроено для обработки в фоновое задание в очереди, нам не обязательно также ставить в очередь обработчик событий уведомлений. Попробуйте удалить интерфейс ShouldQueue, чтобы посмотреть, решит ли это проблему.

Как упоминали другие комментаторы, эта проблема может быть лучше решена с помощью почтовых уведомлений Laravel , которые полностью устраняют необходимость в отдельном обработчике событий NotificationSent.

 4
Author: Cy Rossignol, 2018-07-31 18:35:50