Laravel: уведомление не отправляется по требованию

Я работаю над проектом, используя Laravel. Я хочу использовать события и уведомления. Для контекста: организация может опубликовать задачу (можно сравнить с вакансией). Пользователь может подать заявку на эту работу. Как только Пользователь подает заявку на Задание, электронное письмо должно быть отправлено на контактный адрес электронной почты, сохраненный вместе с Заданием.

Мое событие: ApplicationCreated Мое уведомление: ApplicationCreatedNotification Мой слушатель: SendApplicationCreatedNotification

Моя функция контроллера:

public function store(StoreApplicationRequest $request, Task $task)
{
    Gate::authorize('store', [Application::class, $task]);

    $application = null;

     DB::transaction(function () use ($request, $task, &$application) {
        $application = $task->applications()->create([
            ...$request->validated(),
            'user_id' => auth()->id(),
        ]);
    
        $application->load('user');
        $application->setRelation('task', $task);
     });

        

    ApplicationCreated::dispatch($application);

    return response()->json($application, 201);
}

Моя функция дескриптора в прослушивателе:

public function handle(ApplicationCreated $event): void
{
    $recipient = $event->application->task->contact_email;
    $name = $event->application->task->contact_firstname . ' ' . $event->application->task->contact_lastname;
    Notification::route('mail', [
        $recipient => $name,
    ])
        ->notify(new ApplicationCreatedNotification($event->application));

            
    // @TODO: Send notification to the applicant as well 
    //        something like this:
    //        "You successfully applied to the task: $task->title"
}

И мой тест:

public function test_user_can_apply_to_task(): void
{
    $user = User::factory()->organization()->create();
    $orga = Organization::factory()->forUser($user)->create();
    $task = Task::factory()->forOrganization($orga)->create();

    $basicUser = User::factory()->create();
    Event::fake();
    Notification::fake();

    $response = $this->actingAs($basicUser)->post(route('applications.store', $task->id));

    Event::assertDispatched(ApplicationCreated::class);


    Notification::assertSentOnDemand(ApplicationCreatedNotification::class, function (ApplicationCreatedNotification $notification, array $channels, object $notifiable) use ($task) {
        $recipient = $task->contact_email;
        $name = $task->contact_firstname . ' ' . $task->contact_lastname;
        return $notifiable->routes['mail'] === [$recipient => $name];
    });

    $response->assertStatus(201);

    $this->assertDatabaseHas('applications', [
        'task_id' => $task->id,
        'user_id' => $basicUser->id,
    ]);

}

Я получаю этот вывод:

FAILED  Tests\Feature\CreateApplicationTest > user can apply to task
The expected [App\Notifications\ApplicationCreatedNotification] notification was not sent.
Failed asserting that false is true.

  at vendor\laravel\framework\src\Illuminate\Support\Testing\Fakes\NotificationFake.php:89
     85▕         if (is_numeric($callback)) {
     86▕             return $this->assertSentToTimes($notifiable, $notification, $callback);
     87▕         }
     88▕
  ➜  89▕         PHPUnit::assertTrue(
     90▕             $this->sent($notifiable, $notification, $callback)->count() > 0,
     91▕             "The expected [{$notification}] notification was not sent."
     92▕         );
     93▕     }

  1   vendor\laravel\framework\src\Illuminate\Support\Testing\Fakes\NotificationFake.php:89
  2   vendor\laravel\framework\src\Illuminate\Support\Testing\Fakes\NotificationFake.php:54

Я знаю, что вызывается функция handle, потому что, когда я добавляю dd($recipient, $name); exit(0);, процесс тестирования останавливается, и я получаю этот вывод

"[email protected]" // app\Listeners\SendApplicationCreatedNotification.php:33
"Katrin Thomas" // app\Listeners\SendApplicationCreatedNotification.php:33

Редактировать

После некоторой отладки я обнаружил, что при выполнении моего теста запускается событие NotificationSent. Это событие отправляется классом NotificationSender:

protected function sendToNotifiable($notifiable, $id, $notification, $channel)
    {
        if (! $notification->id) {
            $notification->id = $id;
        }

        if (! $this->shouldSendNotification($notifiable, $notification, $channel)) {
            return;
        }

        $response = $this->manager->driver($channel)->send($notifiable, $notification);

        $this->events->dispatch(
            new NotificationSent($notifiable, $notification, $channel, $response)
        );
    }

Все поддельные уведомления «отправляются» классом NotificationFake, который реализует NotificationDispatcher, который является псевдонимом интерфейса Dispatch.

Похоже, что при отправке уведомления onDemand он не использует класс NotificationFake в качестве своего диспетчера.

Есть ли у кого-нибудь идеи, почему это не работает?

вы уверены, что эта проверка $notifiable->routes['mail'] === [$recipient => $name] верна? Что такое $notifiable->routes['mail']?

kris gjika 31.05.2024 10:50

Если вы добавляете dd (в следующий раз добавьте dump), и он запускается, тогда dump($notifiable->routes['mail'] === [$recipient => $name]) и посмотрите, true или false это, и продолжите базовую отладку.

matiaslauriti 31.05.2024 11:15

@krisgjika нет, я не уверен, но этот код даже не выполняется, так как приложение почему-то не отправляется.

noah1400 31.05.2024 11:20

@matiaslauriti код, на который вы ссылаетесь, находится внутри функции обратного вызова, которая не выполняется. Потому что уведомление не отправляется. Я проверил это с помощью dump и exit(), выходных данных нет, и код не запускается.

noah1400 31.05.2024 11:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
4
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Прочитав документацию, я обнаружил, что вызов Event::fake() предотвратит запуск прослушивателя событий. Поэтому уведомления не будут отправлены. Итак, удаление Event::fake() решает мою проблему.

Другие вопросы по теме