Уведомления
- Введение
- Генерация уведомлений
- Отправка уведомлений
- Использование трейта Notifiable
- Использование фасада Notification
- Определение каналов доставки
- Очереди уведомлений
- Уведомления по запросу
- Почтовые уведомления
- Формирование почтовых сообщений
- Изменение отправителя
- Изменение получателя
- Изменение темы сообщения
- Изменение почтового драйвера
- Изменение почтовых шаблонов
- Почтовые вложения
- Добавление тегов и метаданных
- Настройка сообщения Symfony
- Использование почтовых отправлений
- Предварительный просмотр почтовых уведомлений
- Почтовые уведомления с разметкой Markdown
- Генерация сообщения
- Написание сообщения
- Изменение компонентов
- Уведомления через канал database
- Предварительная подготовка базы данных
- Формирование уведомлений канала database
- Доступ к уведомлениям
- Отметка прочитанных уведомлений
- Трансляция уведомлений
- Предварительная подготовка трансляции
- Формирование транслируемых уведомлений
- Прослушивание транслируемых уведомлений
- Уведомления через SMS
- Предварительная подготовка канала SMS
- Формирование уведомлений через SMS
- Изменение номера отправителя
- Добавление ссылки на клиента
- Маршрутизация SMS-уведомлений
- Уведомления через Slack
- Предварительная подготовка канала Slack
- Формирование уведомления через Slack
- Взаимодействие в Slack
- Маршрутизация уведомлений в Slack
- Уведомление во внешние рабочие пространства Slack
- Локализация уведомлений
- Предпочитаемые пользователем локализации
- Тестирование
- События уведомления
- Пользовательские каналы уведомлений
Введение
В дополнение к поддержке отправки электронной почты, Laravel обеспечивает поддержку отправки уведомлений по различным каналам доставки, включая электронную почту, SMS (через Vonage, бывший Nexmo) и Slack. Кроме того, сообществом было создано множество каналов уведомлений для отправки уведомлений по десяткам различных каналов! Уведомления также могут храниться в базе данных, поэтому они могут быть отображены в вашем веб-интерфейсе.
Как правило, уведомления должны быть короткими информационными сообщениями, которые уведомляют пользователей о том, что произошло в вашем приложении. Например, если вы пишете приложение для выставления счетов, то вы можете отправить своим пользователям уведомление «Счет оплачен» по каналам электронной почты и SMS.
Генерация уведомлений
В Laravel каждое уведомление представлено единым классом. Чтобы сгенерировать новое уведомление, используйте команду make:notification
Artisan. Эта команда поместит новый класс уведомления в каталог app/Notifications
вашего приложения. Если этот каталог не существует в вашем приложении, то Laravel предварительно создаст его:
php artisan make:notification InvoicePaid
Каждый класс уведомления содержит метод via
и переменное количество методов формирования сообщений, таких как toMail
или toDatabase
, которые преобразуют уведомление в сообщение, адаптированное для этого конкретного канала.
Отправка уведомлений
Использование трейта Notifiable
Уведомления могут быть отправлены двумя способами: с использованием метода notify
трейта Notifiable
или с помощью фасада Notification
. Трейт Notifiable
по умолчанию содержится в модели App\Models\User
вашего приложения:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
}
Метод notify
, предоставляемый этим трейтом, ожидает получить экземпляр уведомления:
use App\Notifications\InvoicePaid;
$user->notify(new InvoicePaid($invoice));
Помните, что вы можете использовать трейт
Notifiable
в любой из ваших моделей. Вы не ограничены использованием его только в моделиUser
.
Использование фасада Notification
Как вариант, вы можете отправлять уведомления через фасад Notification
. Этот подход полезен при отправке уведомления нескольким уведомляемым объектам, например группе пользователей. Чтобы отправлять уведомления с помощью фасада, передайте все уведомляемые сущности и экземпляр уведомления методу send
:
use Illuminate\Support\Facades\Notification;
Notification::send($users, new InvoicePaid($invoice));
Вы также можете немедленно отправлять уведомления, используя метод sendNow
. Этот метод немедленно отправит уведомление, даже если оно реализует интерфейс ShouldQueue
:
Notification::sendNow($developers, new DeploymentCompleted($deployment));
Определение каналов доставки
Каждый класс уведомлений имеет метод via
, который определяет, по каким каналам будет доставлено уведомление. Уведомления можно отправлять по каналам mail
, database
, broadcast
, vonage
и slack
.
Если вы хотите использовать другие каналы доставки, такие как Telegram или Pusher, то посетите веб-сайт сообщества Laravel Notification Channels.
Метод via
получает экземпляр $notifiable
, представляющий экземпляр класса, которому отправляется уведомление. Вы можете использовать $notifiable
, чтобы определить, по каким каналам должно доставляться уведомление:
/**
* Получить каналы доставки уведомлений.
*
* @return array<int, string>
*/
public function via(object $notifiable): array
{
return $notifiable->prefers_sms ? ['vonage'] : ['mail', 'database'];
}
Очереди уведомлений
Перед отправкой уведомлений в очередь вы должны настроить и запустить обработчик очереди.
Отправка уведомлений может занять время, особенно если каналу необходимо выполнить внешний вызов API для доставки уведомления. Чтобы ускорить время отклика вашего приложения, поместите ваше уведомление в очередь, добавив интерфейс ShouldQueue
и трейт Queueable
в ваш класс. Интерфейс и трейт уже импортированы для всех уведомлений, сгенерированных с помощью команды make:notification
, поэтому вы можете сразу добавить их в свой класс уведомлений:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
// ...
}
После добавления интерфейса ShouldQueue
к уведомлению вы можете отправить уведомление как обычно. Laravel обнаружит интерфейс ShouldQueue
в классе и автоматически поставит в очередь доставку уведомления:
$user->notify(new InvoicePaid($invoice));
При постановке уведомлений в очередь для каждого получателя и комбинации каналов будет создана задача в очереди. Например, если ваше уведомление имеет три получателя и два канала, в очередь будет отправлено шесть задач.
Отложенные уведомления
Если вы хотите отложить доставку уведомления, то вы можете вызвать метод delay
экземпляра уведомления:
$delay = now()->addMinutes(10);
$user->notify((new InvoicePaid($invoice))->delay($delay));
Вы можете передать массив методу delay
, чтобы указать величину задержки для определенных каналов:
$user->notify((new InvoicePaid($invoice))->delay([
'mail' => now()->addMinutes(5),
'sms' => now()->addMinutes(10),
]));
Как альтернативу, вы можете определить метод withDelay
непосредственно в классе уведомления. Метод withDelay
должен возвращать массив с именами каналов и значениями задержек:
/**
* Определение задержки доставки уведомления.
*
* @return array<string, \Illuminate\Support\Carbon>
*/
public function withDelay(object $notifiable): array
{
return [
'mail' => now()->addMinutes(5),
'sms' => now()->addMinutes(10),
// Задержки для других каналов
];
}
Этот подход позволяет централизованно управлять задержками для разных каналов в одном месте, что упрощает поддержку и модификацию кода.
Изменение соединения отложенных уведомлений
По умолчанию, уведомления, помещенные в очередь, будут использовать стандартное соединение очереди вашего приложения. Если вы хотите указать другое соединение, которое должно использоваться для конкретного уведомления, вы можете вызвать метод onConnection
в конструкторе вашего уведомления:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
/**
* Создание нового экземпляра уведомления.
*/
public function __construct()
{
$this->onConnection('redis');
}
}
Или, если вы хотите указать конкретное соединение с очередью, которое должно использоваться для каждого канала уведомлений, поддерживаемого уведомлением, вы можете определить метод viaConnections
в вашем уведомлении. Этот метод должен возвращать массив пар имя канала / имя соединения с очередью:
/**
* Определение, какое соединение должно использоваться для каждого канала уведомлений.
*
* @return array<string, string>
*/
public function viaConnections(): array
{
return [
'mail' => 'redis',
'database' => 'sync',
];
}
Изменение очереди канала уведомлений
Если вы хотите указать конкретную очередь, которая должна использоваться для каждого канала уведомления, поддерживаемого уведомлением, то вы можете определить метод viaQueues
в своем уведомлении. Этот метод должен возвращать массив пар имя канала / имя очереди:
/**
* Определить, какие очереди следует использовать для каждого канала уведомления.
*
* @return array<string, string>
*/
public function viaQueues(): array
{
return [
'mail' => 'mail-queue',
'slack' => 'slack-queue',
];
}
Посредник для уведомлений в очереди
Уведомления в очереди могут определять промежуточное программное обеспечение так же, как задания в очереди. Для начала определите метод middleware
в своем классе уведомлений. Метод middleware
получит переменные $notifying
и $channel
, которые позволят вам настроить возвращаемое промежуточное программное обеспечение в зависимости от места назначения уведомления:
use Illuminate\Queue\Middleware\RateLimited;
/**
* Get the middleware the notification job should pass through.
*
* @return array<int, object>
*/
public function middleware(object $notifiable, string $channel)
{
return match ($channel) {
'email' => [new RateLimited('postmark')],
'slack' => [new RateLimited('slack')],
default => [],
};
}
Уведомления в очереди и транзакции в базе данных
Когда отложенные уведомления отправляются в транзакциях базы данных, они могут быть обработаны очередью до того, как транзакция базы данных будет зафиксирована. Когда это происходит, любые обновления, внесенные вами в модели или записи базы данных во время транзакции базы данных, могут еще не быть отражены в базе данных. Кроме того, любые модели или записи базы данных, созданные в рамках транзакции, могут не существовать в базе данных.
Если для параметра after_commit
конфигурации вашего соединения с очередью установлено значение false
, то вы все равно можете указать, что конкретное отложенное уведомление должно быть отправлено после того, как все открытые транзакции базы данных были зафиксированы, путем вызова метода afterCommit
при отправке уведомления:
use App\Notifications\InvoicePaid;
$user->notify((new InvoicePaid($invoice))->afterCommit());
В качестве альтернативы вы можете вызвать методafterCommit
из конструктора вашего уведомления:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
/**
* Create a new notification instance.
*/
public function __construct()
{
$this->afterCommit();
}
}
Чтобы узнать больше о том, как обойти эти проблемы, просмотрите документацию, касающуюся заданий в очереди и транзакций базы данных.
Определение необходимости отправки уведомления в очереди
После того как уведомление из очереди было отправлено для фоновой обработки, оно обычно принимается работником очереди и отправляется предполагаемому получателю.
Однако, если вы хотите окончательно определить, следует ли отправлять уведомление в очереди после его обработки работником очереди, вы можете определить метод shouldSend
в классе уведомлений. Если этот метод возвращает false
, уведомление не будет отправлено:
/**
* Определите, нужно ли отправлять уведомление.
*/
public function shouldSend(object $notifiable, string $channel): bool
{
return $this->invoice->isPaid();
}
Уведомления по запросу
По желанию можно отправить уведомление кому-то, кто не сохранен как «пользователь» вашего приложения. Используя метод route
фасада Notification
, вы можете указать информацию о маршрутизации специального уведомления перед отправкой уведомления:
use Illuminate\Broadcasting\Channel;
use Illuminate\Support\Facades\Notification;
Notification::route('mail', 'taylor@example.com')
->route('vonage', '5555555555')
->route('slack', '#slack-channel')
->route('broadcast', [new Channel('channel-name')])
->notify(new InvoicePaid($invoice));
Если вы хотите указать имя получателя при отправке уведомления по запросу на маршрут mail
, вы можете предоставить массив, содержащий адрес электронной почты в качестве ключа и имя в качестве значения первого элемента в массиве:
Notification::route('mail', [
'barrett@example.com' => 'Barrett Blair',
])->notify(new InvoicePaid($invoice));
С помощью метода routes
вы можете предоставить сразу несколько маршрутов для нескольких каналов уведомлений:
Notification::routes([
'mail' => ['barrett@example.com' => 'Barrett Blair'],
'vonage' => '5555555555',
])->notify(new InvoicePaid($invoice));
Почтовые уведомления
Формирование почтовых сообщений
Если уведомление поддерживает отправку по электронной почте, то вы должны определить метод toMail
в классе уведомления. Этот метод получит объект $notifiable
и должен вернуть экземпляр Illuminate\Notifications\Messages\MailMessage
.
Класс MailMessage
содержит несколько простых методов, которые помогут вам создавать транзакционные сообщения электронной почты. Почтовые сообщения могут содержать строки текста, а также «призыв к действию». Давайте посмотрим на пример метода toMail
:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
$url = url('/invoice/'.$this->invoice->id);
return (new MailMessage)
->greeting('Hello!')
->line('One of your invoices has been paid!')
->action('View Invoice', $url)
->line('Thank you for using our application!');
}
Обратите внимание, что мы используем
$this->invoice->id
в нашем методеtoMail
. Вы можете передать любые данные, которые необходимы вашему уведомлению для генерации сообщения, в конструктор уведомления.
В этом примере мы регистрируем приветствие, строку текста, призыв к действию, а затем еще одну строку текста. Эти методы, предоставляемые объектом MailMessage
, упрощают и ускоряют формирование небольших транзакционных электронных писем. Затем канал mail
преобразует компоненты сообщения в красивый, отзывчивый HTML-шаблон сообщения электронной почты с аналогом в виде обычного текста. Вот пример электронного письма, созданного каналом mail
:
При отправке почтовых уведомлений не забудьте установить параметр
name
в вашем конфигурационном файлеconfig/app.php
. Это значение будет использоваться в верхнем и нижнем колонтитулах ваших почтовых уведомлений.
Сообщения об ошибках
Некоторые уведомления информируют пользователей об ошибках, таких как неудачный платеж по счету. Вы можете указать, что почтовое сообщение относится к ошибке, вызвав метод error
при составлении вашего сообщения. При использовании метода error
в почтовом сообщении кнопка действия будет красной, а не черной:
/**
* Получить почтовое представление уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->error()
->subject('Invoice Payment Failed')
->line('...');
}
Этот подход помогает ясно передать пользователю, что сообщение содержит информацию об ошибке, повышая визуальную восприимчивость и понимание сообщения.
Другие параметры формирования почтовых уведомлений
Вместо определения «строк» текста в классе уведомления, вы можете использовать метод view
, чтобы указать собственный шаблон, который следует использовать для отображения почтового уведомления:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->view(
'mail.invoice.paid', ['invoice' => $this->invoice]
);
}
Вы можете определить текстовое содержимое для почтового сообщения, указав имя представления в качестве второго элемента массива, передаваемого методу view
:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->view(
['mail.invoice.paid', 'mail.invoice.paid-text'],
['invoice' => $this->invoice]
);
}
Или, если ваше сообщение содержит только простой текст, вы можете использовать метод text
:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->text(
'mail.invoice.paid-text', ['invoice' => $this->invoice]
);
}
Изменение отправителя
По умолчанию адрес отправителя электронного письма определяется в конфигурационном файле config/mail.php
. Однако вы можете указать адрес отправителя для конкретного уведомления с помощью метода from
:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->from('barrett@example.com', 'Barrett Blair')
->line('...');
}
Изменение получателя
При отправке уведомлений по каналу mail
система уведомлений автоматически ищет свойство email
уведомляемого объекта. Вы можете указать, какой адрес электронной почты будет использоваться для доставки уведомления, определив метод routeNotificationForMail
объекта уведомления:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
class User extends Authenticatable
{
use Notifiable;
/**
* Маршрутизация уведомлений для почтового канала.
*
* @return array<string, string>|string
*/
public function routeNotificationForMail(Notification $notification): array|string
{
// Вернуть только адрес электронной почты ...
return $this->email_address;
// Вернуть адрес электронной почты и имя ...
return [$this->email_address => $this->name];
}
}
Изменение темы сообщения
По умолчанию темой электронного письма является название класса уведомления в регистре «Title Case». Итак, если ваш класс уведомлений называется InvoicePaid
, то темой электронного письма будет «Invoice Paid». Если вы хотите указать другую тему для сообщения, то вы можете вызвать метод subject
при создании своего сообщения:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject('Notification Subject')
->line('...');
}
Изменение почтового драйвера
По умолчанию уведомление по электронной почте будет отправлено с использованием почтового драйвера по умолчанию, определенной в конфигурационном файле config/mail.php
. Однако вы можете указать другой почтовый драйвер во время выполнения, вызвав метод mailer
при создании вашего сообщения:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->mailer('postmark')
->line('...');
}
Изменение почтовых шаблонов
Вы можете изменить шаблон из HTML и обычного текста, используемый для почтовых уведомлений, опубликовав необходимые ресурсы уведомления. После выполнения этой команды шаблоны почтовых уведомлений будут расположены в каталоге resources/views/vendor/notifications
:
php artisan vendor:publish --tag=laravel-notifications
Почтовые вложения
Чтобы добавить вложения к почтовому уведомлению, используйте метод attach
при создании сообщения. Метод attach
принимает абсолютный путь к файлу в качестве своего первого аргумента:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file');
}
Метод
attach
, предоставляемый почтовыми сообщениями уведомлений, также принимает объекты, прикрепляемые к сообщению. Пожалуйста, ознакомьтесь с подробной документацией об объектах, прикрепляемых к сообщениям, чтобы узнать больше.
При прикреплении файлов к сообщению вы также можете указать отображаемое имя и / или MIME-тип, передав массив в качестве второго аргумента методу attach
:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file', [
'as' => 'name.pdf',
'mime' => 'application/pdf',
]);
}
В отличие от прикрепления файлов к почтовым отправлениям, вы не можете прикреплять файл непосредственно с диска файлового хранилища с помощью attachFromStorage
. Лучше использовать метод attach
с абсолютным путем к файлу на диске. В качестве альтернативы вы можете вернуть отправление из метода toMail
:
use App\Mail\InvoicePaid as InvoicePaidMailable;
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): Mailable
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email)
->attachFromStorage('/path/to/file');
}
При необходимости к сообщению можно прикрепить несколько файлов, используя метод attachMany
:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attachMany([
'/path/to/forge.svg',
'/path/to/vapor.svg' => [
'as' => 'Logo.svg',
'mime' => 'image/svg+xml',
],
]);
}
Почтовые вложения необработанных данных
Метод attachData
используется для присоединения необработанной строки в качестве вложения. При вызове метода attachData
вы должны указать имя файла, которое должно быть присвоено вложению:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): Mailable
{
return (new MailMessage)
->greeting('Hello!')
->attachData($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
}
Добавление тегов и метаданных
Некоторые сторонние почтовые провайдеры, такие как Mailgun и Postmark, поддерживают “теги” и “метаданные” сообщений, которые могут использоваться для группировки и отслеживания электронных писем, отправленных вашим приложением. Вы можете добавить теги и метаданные к электронному сообщению с помощью методов tag
и metadata
:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Comment Upvoted!')
->tag('upvote')
->metadata('comment_id', $this->comment->id);
}
Если ваше приложение использует драйвер Mailgun, вы можете обратиться к документации Mailgun для получения дополнительной информации о тегах и метаданных. Аналогично, документацию Postmark можно также проконсультировать для получения информации о их поддержке тегов и метаданных.
Если ваше приложение использует Amazon SES для отправки электронных писем, вы должны использовать метод metadata
для прикрепления тегов SES к сообщению.
Настройка сообщения Symfony
Метод withSymfonyMessage
класса MailMessage
позволяет зарегистрировать функцию обратного вызова, которая будет вызвана с экземпляром сообщения Symfony перед отправкой сообщения. Это дает вам возможность глубоко настроить сообщение перед его доставкой:
use Symfony\Component\Mime\Email;
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->withSymfonyMessage(function (Email $message) {
$message->getHeaders()->addTextHeader(
'Custom-Header', 'Header Value'
);
});
}
Использование почтовых отправлений
При необходимости вы можете вернуть полный объект почтового отправления из метода toMail
вашего уведомления. При возврате Mailable
вместо MailMessage
вам нужно будет указать получателя сообщения с помощью метода to
объекта почтового отправления:
use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Mail\Mailable;
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): Mailable
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email);
}
Почтовые отправления и уведомления по запросу
Если вы отправляете уведомление по запросу, то экземпляр $notifiable
, переданный методу toMail
, будет экземпляром Illuminate\Notifications\AnonymousNotifiable
, содержащий метод routeNotificationFor
, который можно использовать для получения адреса электронной почты для отправления уведомления по запросу:
use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Mail\Mailable;
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): Mailable
{
$address = $notifiable instanceof AnonymousNotifiable
? $notifiable->routeNotificationFor('mail')
: $notifiable->email;
return (new InvoicePaidMailable($this->invoice))
->to($address);
}
Предварительный просмотр почтовых уведомлений
При разработке шаблона почтового уведомления удобно быстро просмотреть визуализированное почтовое сообщение в браузере, как типичный шаблон Blade. По этой причине Laravel позволяет вам возвращать любое почтовое сообщение непосредственно из замыкания маршрута или контроллера. При возврате MailMessage
, оно будет обработано и отображено в браузере, что позволит вам быстро просмотреть его дизайн без необходимости отправлять его на реальный адрес электронной почты:
use App\Models\Invoice;
use App\Notifications\InvoicePaid;
Route::get('/notification', function () {
$invoice = Invoice::find(1);
return (new InvoicePaid($invoice))
->toMail($invoice->user);
});
Почтовые уведомления с разметкой Markdown
Почтовые уведомления с разметкой Markdown позволяют вам воспользоваться преимуществами предварительно созданных шаблонов почтовых уведомлений. Поскольку сообщения написаны на Markdown, Laravel может отображать красивые, отзывчивые HTML-шаблоны для сообщений, а также автоматически генерировать аналог в виде простого текста.
Генерация сообщения
Чтобы сгенерировать уведомление с соответствующим шаблоном Markdown, вы можете использовать параметр --markdown
команды make:notification
Artisan:
php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
Как и все другие почтовые уведомления, уведомления, использующие шаблоны Markdown, должны определять метод toMail
в своем классе уведомлений. Однако вместо использования методов line
и action
для создания уведомления используйте метод markdown
, чтобы указать имя шаблона Markdown, который следует использовать. Массив данных, который вы хотите сделать доступным для шаблона, может быть передан в качестве второго аргумента метода:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
$url = url('/invoice/'.$this->invoice->id);
return (new MailMessage)
->subject('Invoice Paid')
->markdown('mail.invoice.paid', ['url' => $url]);
}
Написание сообщения
Почтовые уведомления Markdown используют комбинацию компонентов Blade и синтаксиса Markdown, которые позволяют легко создавать почтовые уведомления, используя предварительно созданные компоненты уведомлений Laravel:
<x-mail::message>
# Invoice Paid
Your invoice has been paid!
<x-mail::button :url="$url">
View Invoice
</x-mail::button>
Thanks,<br>
{{ config('app.name') }}
</x-mail::message>
Компонент Button
Компонент кнопки отображает ссылку на кнопку по центру. Компонент принимает два аргумента: url
и необязательный color
. Поддерживаемые цвета: primary
, green
, и red
. Вы можете добавить к уведомлению столько компонентов кнопки, сколько захотите:
<x-mail::button :url="$url" color="green">
View Invoice
</x-mail::button>
Компонент Panel
Компонент панели отображает указанный блок текста на панели, цвет фона которой немного отличается от цвета остальной части сообщения. Это позволяет привлечь внимание к указанному блоку текста:
<x-mail::panel>
This is the panel content.
</x-mail::panel>
Компонент Table
Компонент таблицы позволяет преобразовать таблицу Markdown в таблицу HTML. Компонент принимает в качестве содержимого таблицу Markdown. Выравнивание столбцов таблицы поддерживается с использованием синтаксиса выравнивания таблицы Markdown по умолчанию:
<x-mail::table>
| Laravel | Table | Example |
| ------------- | :-----------: | ------------: |
| Col 2 is | Centered | $10 |
| Col 3 is | Right-Aligned | $20 |
</x-mail::table>
Изменение компонентов
Вы можете экспортировать все почтовые компоненты Markdown в собственное приложение для настройки. Чтобы экспортировать компоненты, используйте команду vendor:publish
Artisan с параметром --tag=laravel-mail
:
php artisan vendor:publish --tag=laravel-mail
Эта команда опубликует почтовые компоненты Markdown в каталоге resources/views/vendor/mail
. Каталог mail
будет содержать каталог html
и text
, каждый из которых содержит соответствующие представления каждого доступного компонента. Вы можете настроить эти компоненты по своему усмотрению.
Редактирование файла CSS
После экспорта компонентов в каталоге resources/views/vendor/mail/html/themes
будет содержаться файл default.css
. Вы можете отредактировать CSS в этом файле, и ваши стили будут автоматически преобразованы во встроенные стили CSS в HTML-представлениях ваших почтовых сообщений Markdown.
Если вы хотите создать совершенно новую тему для компонентов Laravel Markdown, вы можете поместить файл CSS в каталог html/themes
. После присвоения имени и сохранения файла CSS обновите параметр theme
в файле конфигурации вашего приложения config/mail.php
, чтобы он соответствовал имени вашей новой темы.
Чтобы настроить тему для отдельного уведомления, вы можете вызвать метод theme
при создании почтового сообщения уведомления. Метод theme
принимает имя темы, которая должна использоваться при отправке уведомления:
/**
* Получить содержимое почтового уведомления.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->theme('invoice')
->subject('Invoice Paid')
->markdown('mail.invoice.paid', ['url' => $url]);
}
Уведомления через канал database
Предварительная подготовка базы данных
Канал уведомлений database
хранит информацию уведомления в таблице базы данных. Эта таблица будет содержать такую информацию, как тип уведомления, а также JSON-структуру данных, которая описывает уведомление.
Вы можете запросить таблицу, чтобы отобразить уведомления в пользовательском интерфейсе вашего приложения. Но прежде чем вы сможете это сделать, вам нужно будет создать таблицу базы данных для хранения ваших уведомлений. Вы можете использовать команду make:notifications-table
для создания миграции с необходимой схемой таблицы:
php artisan make:notifications-table
php artisan migrate
Если ваши модели с уведомлениями используют UUID или ULID в качестве первичных ключей, вы должны заменить метод
morphs
наuuidMorphs
илиulidMorphs
в миграции таблицы уведомлений.
Формирование уведомлений канала database
Чтобы уведомление было сохранено в таблице базы данных, вы должны определить метод toDatabase
или toArray
в классе уведомления. Каждый из этих методов получает объект $notifiable
и должен возвращать простой массив PHP. Возвращенный массив будет закодирован как JSON и сохранен в столбце data
вашей таблицы notifications
. Давайте посмотрим на пример метода toArray
:
/**
* Получить массив данных уведомления.
*
* @return array<string, mixed>
*/
public function toArray(object $notifiable): array
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}
Когда уведомление сохраняется в базе данных вашего приложения, столбец type
заполняется именем класса уведомления. Однако вы можете настроить это поведение, определив метод databaseType
в вашем классе уведомления:
/**
* Получить тип уведомления для базы данных.
*
* @return string
*/
public function databaseType(object $notifiable): string
{
return 'invoice-paid';
}
Этот метод позволяет вам устанавливать пользовательский тип уведомления, который будет сохранен в столбце type
в таблице уведомлений базы данных. Это может быть полезно для более удобного отслеживания и фильтрации уведомлений по типу.
Методы toDatabase и toArray
Метод toArray
также используется каналом broadcast
, чтобы определить, какие данные транслировать в JavaScript-приложение на клиентской стороне. Если вы хотите иметь два разных массива данных для каналов database
и broadcast
, то вы должны определить метод toDatabase
вместо метода toArray
.
Доступ к уведомлениям
После сохранения уведомления в базу данных, вам понадобится удобный способ доступа к нему из уведомляемых объектов. Трейт Illuminate\Notifications\Notifiable
, который по умолчанию расположен в модели App\Models\User
Laravel, содержит отношение notifications
Eloquent, возвращающее уведомления для объекта. Вы можете обратиться к этому методу, как и к любому другому отношению Eloquent, чтобы получить уведомления. По умолчанию уведомления будут упорядочены по столбцу created_at
временной метки, причем самые последние уведомления будут помещены в начало коллекции:
$user = App\Models\User::find(1);
foreach ($user->notifications as $notification) {
echo $notification->type;
}
Для получения только «непрочитанных» уведомлений, используйте отношение unreadNotifications
. Опять же, эти уведомления будут упорядочены по столбцу created_at
временной метки с самыми последними уведомлениями в начале коллекции:
$user = App\Models\User::find(1);
foreach ($user->unreadNotifications as $notification) {
echo $notification->type;
}
Чтобы получить доступ к уведомлениям в JavaScript-приложении на клиентской стороне, вы должны определить контроллер уведомлений для своего приложения, который возвращает уведомления для уведомляемого объекта, такого как текущий пользователь. Затем вы можете сделать HTTP-запрос к URL-адресу этого контроллера из своего JavaScript-приложения на клиентской стороне.
Отметка прочитанных уведомлений
По желанию можно пометить уведомление как «прочитанное», когда пользователь его просматривает. Трейт Illuminate\Notifications\Notifiable
содержит метод markAsRead
, который обновляет столбец read_at
записи уведомления в базе данных:
$user = App\Models\User::find(1);
foreach ($user->unreadNotifications as $notification) {
$notification->markAsRead();
}
Однако вместо того, чтобы перебирать каждое уведомление, вы можете использовать метод markAsRead
непосредственно для коллекции уведомлений:
$user->unreadNotifications->markAsRead();
Вы также можете выполнить запрос массового обновления, чтобы пометить все уведомления как прочитанные, не извлекая их из базы данных:
$user = App\Models\User::find(1);
$user->unreadNotifications()->update(['read_at' => now()]);
Вы можете полностью удалить уведомления из таблицы, используя метод delete
:
$user->notifications()->delete();
Трансляция уведомлений
Предварительная подготовка трансляции
Перед трансляцией уведомлений вы должны настроить и ознакомиться со службами трансляции событий Laravel. Трансляция событий – способ реагирования на серверные события Laravel из своего JavaScript-приложения на клиентской стороне.
Формирование транслируемых уведомлений
Канал broadcast
транслирует уведомления с использованием служб трансляции событий Laravel, что позволяет вашему JavaScript-приложению на клиентской стороне улавливать уведомления в режиме реального времени. Если уведомление поддерживает трансляцию, то вы должны определить метод toBroadcast
в классе уведомления. Этот метод получит объект $notifiable
и должен вернуть экземпляр BroadcastMessage
. Если метод toBroadcast
не существует, то метод toArray
будет использоваться для сбора данных, которые следует транслировать. Возвращенные данные будут закодированы как JSON и переданы вашему JavaScript-приложению на клиентской стороне. Давайте посмотрим на пример метода toBroadcast
:
use Illuminate\Notifications\Messages\BroadcastMessage;
/**
* Получить содержимое транслируемого уведомления.
*/
public function toBroadcast(object $notifiable): BroadcastMessage
{
return new BroadcastMessage([
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
]);
}
Конфигурирование очереди трансляции
Все транслируемые уведомления ставятся в очередь для трансляции. Если вы хотите изменить соединение очереди или имя очереди, которое используется для постановки в очередь трансляции, то вы можете использовать методы onConnection
и onQueue
экземпляра BroadcastMessage
:
return (new BroadcastMessage($data))
->onConnection('sqs')
->onQueue('broadcasts');
Изменение типа транслируемого уведомления
В дополнение к указанным вами данным все транслируемые уведомления также имеют поле type
, содержащее полное имя класса уведомления. Если вы хотите изменить type
уведомления, то вы можете определить метод broadcastType
в классе уведомления:
/**
* Получить тип транслируемого уведомления.
*/
public function broadcastType(): string
{
return 'broadcast.message';
}
Прослушивание транслируемых уведомлений
Уведомления будут транслироваться по частному каналу, в формате с использованием соглашения {notifiable}.{id}
. Итак, если вы отправляете уведомление экземпляру App\Models\User
с идентификатором 1
, то уведомление будет транслироваться по частному каналу App.Models.User.1
. При использовании Laravel Echo вы можете легко прослушивать уведомления канала, используя метод notification
:
Echo.private('App.Models.User.' + userId)
.notification((notification) => {
console.log(notification.type);
});
Изменение канала транслируемого уведомления
Если вы хотите изменить канал, на котором транслируются уведомления объекта, то вы можете определить метод receivesBroadcastNotificationsOn
объекта уведомления:
<?php
namespace App\Models;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use Notifiable;
/**
* Каналы, по которым пользователь получает рассылку уведомлений.
*/
public function receivesBroadcastNotificationsOn(): string
{
return 'users.'.$this->id;
}
}
Уведомления через SMS
Предварительная подготовка канала SMS
Отправка SMS-уведомлений в Laravel обеспечивается Vonage (бывший Nexmo).
Прежде чем вы сможете отправлять уведомления через Vonage, вам необходимо установить пакеты laravel/vonage-notification-channel
и guzzlehttp/guzzle
:
composer require laravel/vonage-notification-channel guzzlehttp/guzzle
Пакет включает в себя файл конфигурации. Однако вам не обязательно экспортировать этот файл конфигурации в ваше собственное приложение. Вы можете просто использовать переменные окружения VONAGE_KEY
и VONAGE_SECRET
для определения ваших публичного и секретного ключей Vonage.
После определения ваших ключей, вы должны установить переменную окружения VONAGE_SMS_FROM
, которая определяет номер телефона, с которого по умолчанию будут отправляться ваши SMS-сообщения. Вы можете сгенерировать этот номер телефона в панели управления Vonage:
VONAGE_SMS_FROM=15556666666
Формирование уведомлений через SMS
Если уведомление поддерживает отправку в виде SMS, то вы должны определить метод toVonage
в классе уведомлений. Этот метод получит объект $notifiable
и должен вернуть экземпляр Illuminate\Notifications\Messages\NexmoMessage
:
/**
* Получить SMS-представление уведомления.
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content('Your SMS message content');
}
Содержимое Unicode
Если ваше SMS-сообщение будет содержать символы Unicode, то вы должны вызвать метод unicode
при создании экземпляра VonageMessage
:
use Illuminate\Notifications\Messages\VonageMessage;
/**
* Получить SMS-представление уведомления.
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content('Your unicode message')
->unicode();
}
Изменение номера отправителя
Если вы хотите отправить уведомление с номера телефона, который отличается от номера телефона, указанного в вашем файле config/services.php
, то вы можете вызвать метод from
экземпляра VonageMessage
:
/**
* Получить Vonage / SMS-представление уведомления.
*
* @param mixed $notifiable
* @return NexmoMessage
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content('Your SMS message content')
->from('15554443333');
}
Добавление ссылки на клиента
Если вы хотите отслеживать затраты на пользователя, команду или клиента, вы можете добавить в уведомление “ссылку на клиента”. Vonage позволит вам создавать отчеты, используя эту ссылку клиента, чтобы вы могли лучше понять использование SMS конкретным клиентом. Ссылка на клиента может быть любой строкой до 40 символов:
/**
* Получить Vonage / SMS-представление уведомления.
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->clientReference((string) $notifiable->id)
->content('Your SMS message content');
}
Маршрутизация SMS-уведомлений
Для отправки уведомления с использованием Vonage на необходимый номер телефона, определите метод routeNotificationForVonage
вашего уведомляемого объекта:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
class User extends Authenticatable
{
use Notifiable;
/**
* Маршрутизация уведомлений для канала Vonage.
*/
public function routeNotificationForVonage(Notification $notification): string
{
return $this->phone_number;
}
}
Уведомления через Slack
Предварительная подготовка канала Slack
Прежде чем вы сможете отправлять уведомления через Slack, вы должны установить канал уведомлений Slack через Composer:
composer require laravel/slack-notification-channel
Дополнительно, вы должны создать Slack приложение для вашего рабочего пространства Slack.
Если вам нужно отправлять уведомления только в то же рабочее пространство Slack, в котором создано приложение, убедитесь, что ваше приложение имеет разрешения chat:write
, chat:write.public
и chat:write.customize
. Если вы хотите отправлять сообщения в качестве приложения Slack, вам следует убедиться, что ваше приложение также имеет область действия chat:write:bot
. Эти разрешения можно добавить на вкладке “OAuth & Permissions” в управлении приложениями Slack.
Далее, скопируйте “Bot User OAuth Token” вашего приложения и поместите его в массив конфигурации slack
в файле конфигурации services.php
вашего приложения. Этот токен можно найти на вкладке “OAuth & Permissions” в Slack:
'slack' => [
'notifications' => [
'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
],
],
Распространение приложения Slack
Если ваше приложение будет отправлять уведомления во внешние рабочие пространства Slack, которые принадлежат пользователям вашего приложения, вам нужно будет “распространить” ваше приложение через Slack. Управление распространением приложения можно осуществить на вкладке “Manage Distribution” вашего приложения в Slack. После того, как ваше приложение будет распространено, вы можете использовать Socialite, чтобы получать токены Slack Bot от имени пользователей вашего приложения.
Формирование уведомления через Slack
Если уведомление поддерживает отправку в виде сообщения Slack, вы должны определить метод toSlack
в классе уведомления. Этот метод получает сущность $notifiable
и должен возвращать экземпляр Illuminate\Notifications\Slack\SlackMessage
. Вы можете создавать богатые уведомления, используя API Block Kit Slack. Следующий пример может быть предпросмотрен в Block Kit Builder Slack:
use Illuminate\Notifications\Slack\BlockKit\Blocks\ContextBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\SectionBlock;
use Illuminate\Notifications\Slack\BlockKit\Composites\ConfirmObject;
use Illuminate\Notifications\Slack\SlackMessage;
/**
* Получить представление Slack-уведомления.
*/
public function toSlack(object $notifiable): SlackMessage
{
return (new SlackMessage)
->text('One of your invoices has been paid!')
->headerBlock('Invoice Paid')
->contextBlock(function (ContextBlock $block) {
$block->text('Customer #1234');
})
->sectionBlock(function (SectionBlock $block) {
$block->text('An invoice has been paid.');
$block->field("*Invoice No:*\n1000")->markdown();
$block->field("*Invoice Recipient:*\ntaylor@laravel.com")->markdown();
})
->dividerBlock()
->sectionBlock(function (SectionBlock $block) {
$block->text('Congratulations!');
});
}
Использование шаблона Block Kit Builder Slack
Вместо использования методов построителя сообщений для создания сообщения Block Kit вы можете передать необработанный JSON, сгенерированный Block Kit Builder Slack, методу usingBlockKitTemplate:
use Illuminate\Notifications\Slack\SlackMessage;
use Illuminate\Support\Str;
/**
* Get the Slack representation of the notification.
*/
public function toSlack(object $notifiable): SlackMessage
{
$template = <<<JSON
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "Team Announcement"
}
},
{
"type": "section",
"text": {
"type": "plain_text",
"text": "We are hiring!"
}
}
]
}
JSON;
return (new SlackMessage)
->usingBlockKitTemplate($template);
}
Взаимодействие в Slack
Система уведомлений Block Kit Slack предлагает мощные функции для обработки взаимодействия пользователя. Чтобы использовать эти функции, ваше приложение Slack должно иметь включенную функцию “Interactivity” и настроенный “Request URL”, который указывает на URL, обслуживаемый вашим приложением. Эти настройки можно управлять на вкладке “Interactivity & Shortcuts” в управлении приложениями Slack.
В следующем примере, который использует метод actionsBlock
, Slack отправит POST
запрос на ваш “Request URL” с полезной нагрузкой, содержащей пользователя Slack, который нажал на кнопку, идентификатор нажатой кнопки и дополнительную информацию. Ваше приложение может затем определить, какое действие следует предпринять на основе полученной полезной нагрузки. Также вы должны проверить подлинность запроса, чтобы убедиться, что он был сделан Slack:
use Illuminate\Notifications\Slack\BlockKit\Blocks\ActionsBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\ContextBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\SectionBlock;
use Illuminate\Notifications\Slack\SlackMessage;
/**
* Получить представление Slack-уведомления.
*/
public function toSlack(object $notifiable): SlackMessage
{
return (new SlackMessage)
->text('One of your invoices has been paid!')
->headerBlock('Invoice Paid')
->contextBlock(function (ContextBlock $block) {
$block->text('Customer #1234');
})
->sectionBlock(function (SectionBlock $block) {
$block->text('An invoice has been paid.');
})
->actionsBlock(function (ActionsBlock $block) {
// ID defaults to "button_acknowledge_invoice"...
$block->button('Acknowledge Invoice')->primary();
// Manually configure the ID...
$block->button('Deny')->danger()->id('deny_invoice');
});
}
Модальные окна подтверждения
Если вы хотите, чтобы пользователи подтверждали действие перед его выполнением, вы можете использовать метод confirm
при определении вашей кнопки. Метод confirm
принимает сообщение и замыкание, которое получает экземпляр ConfirmObject
:
use Illuminate\Notifications\Slack\BlockKit\Blocks\ActionsBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\ContextBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\SectionBlock;
use Illuminate\Notifications\Slack\BlockKit\Composites\ConfirmObject;
use Illuminate\Notifications\Slack\SlackMessage;
/**
* Получить представление Slack-уведомления.
*/
public function toSlack(object $notifiable): SlackMessage
{
return (new SlackMessage)
->text('One of your invoices has been paid!')
->headerBlock('Invoice Paid')
->contextBlock(function (ContextBlock $block) {
$block->text('Customer #1234');
})
->sectionBlock(function (SectionBlock $block) {
$block->text('An invoice has been paid.');
})
->actionsBlock(function (ActionsBlock $block) {
$block->button('Acknowledge Invoice')
->primary()
->confirm(
'Acknowledge the payment and send a thank you email?',
function (ConfirmObject $dialog) {
$dialog->confirm('Yes');
$dialog->deny('No');
}
);
});
}
Просмотр cтруктуры блоков Slack
Если вы хотите быстро проверить структуру блоков, которые вы создали, вы можете использовать метод dd
в экземпляре SlackMessage
. Метод dd
сгенерирует и выведет URL-адрес для Block Kit Builder Slack, который отображает предварительный просмотр полезной нагрузки и уведомления в вашем браузере. Вы можете передать true
методу dd
, чтобы вывести сырую полезную нагрузку:
return (new SlackMessage)
->text('Один из ваших счетов оплачен!')
->headerBlock('Счет Оплачен')
->dd(); // Это вызовет просмотр блоков в Block Kit Builder
Этот метод особенно полезен во время разработки, так как позволяет быстро и удобно проверить внешний вид и структуру ваших уведомлений в Slack, не отправляя их на самом деле.
Маршрутизация уведомлений в Slack
Чтобы направлять уведомления Slack в соответствующую команду Slack и канал, определите метод routeNotificationForSlack
в вашей модели, уведомляемой событиями. Этот метод может возвращать одно из трех значений:
null
– что означает использование маршрутизации к каналу, настроенному в самом уведомлении. Вы можете использовать методto
при создании вашегоSlackMessage
для настройки канала в уведомлении.- Строку, указывающую Slack канал, куда следует отправить уведомление, например,
#support-channel
. - Экземпляр
SlackRoute
, который позволяет вам указать OAuth токен и имя канала, например,SlackRoute::make($this->slack_channel, $this->slack_token)
. Этот метод следует использовать для отправки уведомлений во внешние рабочие пространства.
Например, возвращение #support-channel
из метода routeNotificationForSlack
отправит уведомление в канал #support-channel
рабочего пространства, связанного с OAuth токеном Bot User, расположенным в файле конфигурации services.php
вашего приложения:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
class User extends Authenticatable
{
use Notifiable;
/**
* Маршрутизация уведомлений для канала Slack.
*/
public function routeNotificationForSlack(Notification $notification): string
{
return '#support-channel';
}
}
Уведомление во внешние рабочие пространства Slack
Прежде чем отправлять уведомления во внешние рабочие пространства Slack, ваше приложение Slack должно быть распространено.
Конечно, часто вам захочется отправлять уведомления в рабочие пространства Slack, которые принадлежат пользователям вашего приложения. Для этого сначала вам потребуется получить OAuth-токен Slack для пользователя. К счастью, Laravel Socialite включает драйвер Slack, который позволит вам легко аутентифицировать пользователей вашего приложения в Slack и получать токен бота.
После получения токена бота и его сохранения в базе данных вашего приложения, вы можете использовать метод SlackRoute::make
для направления уведомления в рабочее пространство пользователя. Кроме того, ваше приложение, скорее всего, должно предоставить пользователю возможность указать, в какой канал следует отправлять уведомления:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Slack\SlackRoute;
class User extends Authenticatable
{
use Notifiable;
/**
* Маршрутизация уведомлений для канала Slack.
*
* @param \Illuminate\Notifications\Notification $notification
* @return string
*/
public function routeNotificationForSlack(Notification $notification): mixed
{
return SlackRoute::make($this->slack_channel, $this->slack_token);
}
}
Локализация уведомлений
Laravel позволяет отправлять уведомления, используя язык, отличный от текущего языка запроса, и даже будет помнить его, если уведомление находится в очереди.
Для этого класс Illuminate\Notifications\Notification
содержит метод locale
для установки желаемого языка. Приложение изменит язык при анализе уведомления, а затем вернется к предыдущему языку, когда анализ будет завершен:
$user->notify((new InvoicePaid($invoice))->locale('es'));
Локализация нескольких уведомляемых записей также доступна через фасад Notification
:
Notification::locale('es')->send(
$users, new InvoicePaid($invoice)
);
Предпочитаемые пользователем локализации
Иногда приложения хранят предпочтительный язык каждого пользователя. Реализуя контракт HasLocalePreference
в вашей уведомляемой модели, вы можете указать Laravel использовать этот сохраненный язык при отправке уведомления:
use Illuminate\Contracts\Translation\HasLocalePreference;
class User extends Model implements HasLocalePreference
{
/**
* Получить предпочитаемую пользователем локализацию.
*/
public function preferredLocale(): string
{
return $this->locale;
}
}
После того как вы реализовали интерфейс, Laravel будет автоматически использовать предпочтительный язык при отправке уведомлений и почтовых сообщений модели. Следовательно, при использовании этого интерфейса нет необходимости вызывать метод locale
:
$user->notify(new InvoicePaid($invoice));
Тестирование
Вы можете использовать метод fake
фасада Notification
, чтобы предотвратить отправку уведомлений. Как правило, отправка уведомлений не имеет отношения к коду, который вы фактически тестируете. Вероятно, будет достаточно просто утверждать, что Laravel получил инструкцию отправить определенное уведомление.
После вызова метода fake
фасада Notification
, вы можете проверить, было ли передано инструкции отправить уведомления пользователям, и даже проверить данные, полученные уведомлениями:
<?php
use App\Notifications\OrderShipped;
use Illuminate\Support\Facades\Notification;
test('orders can be shipped', function () {
Notification::fake();
// Выполняем доставку заказа...
// Утверждаем, что уведомления не были отправлены...
Notification::assertNothingSent();
// Утверждаем, что уведомление было отправлено указанным пользователям...
Notification::assertSentTo(
[$user], OrderShipped::class
);
// Утверждаем, что уведомление не было отправлено...
Notification::assertNotSentTo(
[$user], AnotherNotification::class
);
// Утверждаем, что было отправлено заданное количество уведомлений...
Notification::assertCount(3);
});
<?php
namespace Tests\Feature;
use App\Notifications\OrderShipped;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_orders_can_be_shipped(): void
{
Notification::fake();
// Выполняем доставку заказа...
// Утверждаем, что уведомления не были отправлены...
Notification::assertNothingSent();
// Утверждаем, что уведомление было отправлено указанным пользователям...
Notification::assertSentTo(
[$user], OrderShipped::class
);
// Утверждаем, что уведомление не было отправлено...
Notification::assertNotSentTo(
[$user], AnotherNotification::class
);
// Утверждаем, что было отправлено заданное количество уведомлений...
Notification::assertCount(3);
}
}
Вы можете передать замыкание в методы assertSentTo
или assertNotSentTo
, чтобы проверить, что было отправлено уведомление, которое проходит заданный “тест истины”. Если хотя бы одно уведомление было отправлено и прошло заданный тест, то утверждение будет успешным:
Notification::assertSentTo(
$user,
function (OrderShipped $notification, array $channels) use ($order) {
return $notification->order->id === $order->id;
}
);
Уведомления по требованию
Если код, который вы тестируете, отправляет уведомления по требованию, вы можете проверить, что уведомление по требованию было отправлено с помощью метода assertSentOnDemand
:
Notification::assertSentOnDemand(OrderShipped::class);
Передав замыкание вторым аргументом метода assertSentOnDemand
, вы можете определить, отправлено ли уведомление по требованию на правильный “маршрут”:
Notification::assertSentOnDemand(
OrderShipped::class,
function (OrderShipped $notification, array $channels, object $notifiable) use ($user) {
return $notifiable->routes['mail'] === $user->email;
}
);
События уведомления
Событие отправки уведомления
При отправке уведомления, система уведомлений запускает событие Illuminate\Notifications\Events\NotificationSending
. Он содержит «уведомляемый» объект и сам экземпляр уведомления. Вы можете создать прослушиватели событий для этого события в своем приложении:
use Illuminate\Notifications\Events\NotificationSending;
class CheckNotificationStatus
{
/**
* Handle the given event.
*/
public function handle(NotificationSending $event): void
{
// ...
}
}
Уведомление не будет отправлено, если прослушиватель событий NotificationSending возвращает false
из своего метода handle
:
/**
* Обработка данного события.
*/
public function handle(NotificationSending $event): bool
{
return false;
}
В слушателе событий вы можете получить доступ к свойствам notifiable
, notification
и channel
события, чтобы узнать больше о получателе уведомления или самом уведомлении:
/**
* Обработка данного события.
*/
public function handle(NotificationSending $event): void
{
// $event->channel
// $event->notifiable
// $event->notification
}
Событие после отправки уведомления
Когда уведомление отправлено, система уведомлений запускает событие Illuminate\Notifications\Events\NotificationSent
. Событие содержит уведомляемую сущность и сам экземпляр уведомления. Вы можете создать прослушиватели событий для этого события в своем приложении:
use Illuminate\Notifications\Events\NotificationSent;
class LogNotification
{
/**
* Обработать переданное событие.
*/
public function handle(NotificationSent $event): void
{
// ...
}
}
В слушателе события вы можете получить доступ к свойствам notifiable
, notification
, channel
и response
события, чтобы узнать больше о получателе уведомления или самом уведомлении:
/**
* Обработать переданное событие.
*/
public function handle(NotificationSent $event): void
{
// $event->channel
// $event->notifiable
// $event->notification
// $event->response
}
Пользовательские каналы уведомлений
Laravel предлагает несколько каналов уведомлений, но вы можете написать свои собственные драйверы для доставки уведомлений по другим каналам. С Laravel это сделать просто. Для начала определите класс, содержащий метод send
. Этот метод должен получать два аргумента: $notifiable
и $notification
.
В методе send
вы можете вызывать методы уведомления, чтобы получить объект сообщения, понятный вашему каналу, а затем отправить уведомление необходимому экземпляру $notifiable
:
<?php
namespace App\Notifications;
use Illuminate\Notifications\Notification;
class VoiceChannel
{
/**
* Отправить переданное уведомление.
*/
public function send(object $notifiable, Notification $notification): void
{
$message = $notification->toVoice($notifiable);
// Отправка уведомления экземпляру `$notifiable` ...
}
}
Как только ваш класс канала уведомления был определен, вы можете вернуть имя класса из метода via
любого из ваших уведомлений. В этом примере метод вашего уведомления toVoice
может возвращать любой объект для формирования голосовых сообщений. Например, вы можете определить свой собственный класс VoiceMessage
для формирования таких сообщений:
<?php
namespace App\Notifications;
use App\Notifications\Messages\VoiceMessage;
use App\Notifications\VoiceChannel;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification
{
use Queueable;
/**
* Получить каналы доставки уведомлений.
*/
public function via(object $notifiable): string
{
return VoiceChannel::class;
}
/**
* Получить содержимое голосового сообщения.
*/
public function toVoice(object $notifiable): VoiceMessage
{
// ...
}
}