Сповіщення
Вступ
Окрім підтримки надсилання пошти, Laravel підтримує надсилання сповіщень різними каналами доставки: електронною поштою, SMS (через Vonage, раніше відомий як Nexmo) та Slack. Крім того, спільнота створила чимало каналів сповіщень, які дозволяють надсилати сповіщення десятками різних каналів! Сповіщення можна також зберігати в базі даних, щоб показувати їх у вебінтерфейсі.
Зазвичай сповіщення мають бути короткими інформаційними повідомленнями, які розповідають користувачам про щось, що сталося у вашому застосунку. Наприклад, якщо ви пишете застосунок для виставлення рахунків, ви можете надсилати користувачам сповіщення «Рахунок оплачено» каналами пошти та SMS.
Генерація сповіщень
У Laravel кожне сповіщення представлено окремим класом, який зазвичай зберігається в каталозі app/Notifications. Не переймайтеся, якщо цього каталогу у вашому застосунку немає - його буде створено, коли ви виконаєте команду Artisan make:notification:
php artisan make:notification InvoicePaid
Ця команда покладе свіжий клас сповіщення до каталогу app/Notifications. Кожен клас сповіщення містить метод 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, щоб визначити, якими каналами слід доставити сповіщення:
/**
* Get the notification's delivery channels.
*
* @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()->plus(minutes: 10);
$user->notify((new InvoicePaid($invoice))->delay($delay));
Ви можете передати методу delay масив, щоб задати затримку для конкретних каналів:
$user->notify((new InvoicePaid($invoice))->delay([
'mail' => now()->plus(minutes: 5),
'sms' => now()->plus(minutes: 10),
]));
Як варіант, ви можете описати метод withDelay у самому класі сповіщення. Метод withDelay має повернути масив назв каналів і значень затримки:
/**
* Determine the notification's delivery delay.
*
* @return array<string, \Illuminate\Support\Carbon>
*/
public function withDelay(object $notifiable): array
{
return [
'mail' => now()->plus(minutes: 5),
'sms' => now()->plus(minutes: 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;
/**
* Create a new notification instance.
*/
public function __construct()
{
$this->onConnection('redis');
}
}
Або ж, якщо ви хочете вказати конкретне підключення черги для кожного каналу, який підтримує сповіщення, опишіть у сповіщенні метод viaConnections. Цей метод має повернути масив пар «назва каналу - назва підключення черги»:
/**
* Determine which connections should be used for each notification channel.
*
* @return array<string, string>
*/
public function viaConnections(): array
{
return [
'mail' => 'redis',
'database' => 'sync',
];
}
Налаштування черг каналів сповіщень
Якщо ви хочете вказати конкретну чергу для кожного каналу, який підтримує сповіщення, опишіть у сповіщенні метод viaQueues. Цей метод має повернути масив пар «назва каналу - назва черги»:
/**
* Determine which queues should be used for each notification channel.
*
* @return array<string, string>
*/
public function viaQueues(): array
{
return [
'mail' => 'mail-queue',
'slack' => 'slack-queue',
];
}
Налаштування атрибутів завдання сповіщення в черзі
Ви можете налаштувати поведінку завдання в черзі, описавши атрибути черги у класі сповіщення. Ці атрибути успадкує завдання, яке надсилатиме сповіщення:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Queue\Attributes\MaxExceptions;
use Illuminate\Queue\Attributes\Timeout;
use Illuminate\Queue\Attributes\Tries;
#[Tries(5)]
#[Timeout(120)]
#[MaxExceptions(3)]
class InvoicePaid extends Notification implements ShouldQueue
{
use Queueable;
// ...
}
Якщо ви хочете забезпечити приватність і цілісність даних сповіщення в черзі за допомогою шифрування, додайте до класу сповіщення інтерфейс ShouldBeEncrypted:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
class InvoicePaid extends Notification implements ShouldQueue, ShouldBeEncrypted
{
use Queueable;
// ...
}
Окрім опису цих атрибутів безпосередньо у класі сповіщення, ви можете описати методи backoff та retryUntil, щоб задати стратегію відступу й таймаут повторів для завдання сповіщення в черзі:
use DateTime;
/**
* Calculate the number of seconds to wait before retrying the notification.
*/
public function backoff(): int
{
return 3;
}
/**
* Determine the time at which the notification should timeout.
*/
public function retryUntil(): DateTime
{
return now()->plus(minutes: 5);
}
Докладніше про ці атрибути й методи завдань читайте в документації про завдання в черзі.
Middleware сповіщень у черзі
Сповіщення в черзі можуть описувати middleware так само, як завдання в черзі. Для початку опишіть у класі сповіщення метод middleware. Метод middleware отримає змінні $notifiable та $channel, що дозволяє налаштувати повернений middleware залежно від призначення сповіщення:
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) {
'mail' => [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, сповіщення не буде надіслано:
/**
* Determine if the notification should be sent.
*/
public function shouldSend(object $notifiable, string $channel): bool
{
return $this->invoice->isPaid();
}
Після надсилання сповіщень
Якщо ви хочете виконати код після того, як сповіщення надіслано, опишіть у класі сповіщення метод afterSending. Цей метод отримає сутність-отримувача, назву каналу та відповідь від каналу:
/**
* Handle the notification after it has been sent.
*/
public function afterSending(object $notifiable, string $channel, mixed $response): void
{
// ...
}
Сповіщення на льоту
Інколи вам може знадобитися надіслати сповіщення комусь, хто не зберігається як «користувач» вашого застосунку. Метод 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:
/**
* Get the mail representation of the notification.
*/
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!')
->lineIf($this->amount > 0, "Amount paid: {$this->amount}")
->action('View Invoice', $url)
->line('Thank you for using our application!');
}
Зверніть увагу: у методі
toMailми використовуємо$this->invoice->id. Ви можете передати в конструктор сповіщення будь-які дані, потрібні йому для формування повідомлення.
У цьому прикладі ми реєструємо привітання, рядок тексту, заклик до дії й ще один рядок тексту. Ці методи об'єкта MailMessage роблять форматування невеликих транзакційних листів простим і швидким. Далі поштовий канал перетворить складові повідомлення на гарний адаптивний HTML-шаблон із текстовим відповідником. Ось приклад листа, згенерованого каналом mail:
Надсилаючи поштові сповіщення, обов'язково задайте опцію конфігурації
nameу файліconfig/app.php. Це значення використовуватиметься в шапці та підвалі ваших поштових сповіщень.
Повідомлення про помилки
Деякі сповіщення інформують користувачів про помилки - наприклад, про невдалу оплату рахунка. Ви можете вказати, що поштове повідомлення стосується помилки, викликавши метод error під час його побудови. Коли ви користуєтеся методом error, кнопка заклику до дії буде червоною, а не чорною:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->error()
->subject('Invoice Payment Failed')
->line('...');
}
Інші варіанти форматування поштових сповіщень
Замість описувати «рядки» тексту у класі сповіщення, ви можете скористатися методом view, щоб указати власний шаблон для рендерингу листа сповіщення:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->view(
'mail.invoice.paid', ['invoice' => $this->invoice]
);
}
Текстове представлення поштового повідомлення можна вказати, передавши назву представлення другим елементом масиву, який передається методу view:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->view(
['mail.invoice.paid', 'mail.invoice.paid-text'],
['invoice' => $this->invoice]
);
}
Або ж, якщо ваше повідомлення має лише текстове представлення, скористайтеся методом text:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->text(
'mail.invoice.paid-text', ['invoice' => $this->invoice]
);
}
Налаштування відправника
За замовчуванням відправника / адресу «from» листа задано у файлі конфігурації config/mail.php. Проте ви можете вказати адресу «from» для конкретного сповіщення методом from:
/**
* Get the mail representation of the notification.
*/
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;
/**
* Route notifications for the mail channel.
*
* @return array<string, string>|string
*/
public function routeNotificationForMail(Notification $notification): array|string
{
// Return email address only...
return $this->email_address;
// Return email address and name...
return [$this->email_address => $this->name];
}
}
Налаштування теми
За замовчуванням темою листа є назва класу сповіщення, відформатована в «Title Case». Тож, якщо ваш клас сповіщення називається InvoicePaid, темою листа буде Invoice Paid. Якщо ви хочете вказати іншу тему, викличте метод subject під час побудови повідомлення:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject('Notification Subject')
->line('...');
}
Налаштування мейлера
За замовчуванням поштове сповіщення надсилається мейлером за замовчуванням, описаним у файлі config/mail.php. Проте ви можете вказати інший мейлер під час виконання, викликавши метод mailer під час побудови повідомлення:
/**
* Get the mail representation of the notification.
*/
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 приймає першим аргументом абсолютний шлях до файлу:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file');
}
Метод
attachпоштових повідомлень сповіщень також приймає об'єкти, придатні для вкладення. Щоб дізнатися більше, перегляньте вичерпну документацію про такі об'єкти.
Вкладаючи файли до повідомлення, ви можете вказати відображувану назву та / або MIME-тип, передавши array другим аргументом методу attach:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file', [
'as' => 'name.pdf',
'mime' => 'application/pdf',
]);
}
За потреби до повідомлення можна вкласти кілька файлів методом attachMany:
/**
* Get the mail representation of the notification.
*/
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',
],
]);
}
Метод attachFromStorageDisk дозволяє вкласти файл, що лежить на конкретному диску файлової системи. Цей метод приймає назву диска й шлях до файлу на ньому:
use App\Mail\InvoicePaid as InvoicePaidMailable;
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): Mailable
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email)
->attachFromStorageDisk('s3', '/path/to/file', 'invoice.pdf', [
'mime' => 'application/pdf',
]);
}
Вкладення сирих даних
Метод attachData дозволяє вкласти сирий рядок байтів як вкладення. Викликаючи метод attachData, передайте ім'я файлу, яке слід призначити вкладенню:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attachData($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
}
Додавання тегів і метаданих
Деякі сторонні поштові провайдери на кшталт Mailgun і Postmark підтримують «теги» й «метадані» повідомлень, які дозволяють групувати та відстежувати листи, надіслані вашим застосунком. Додати теги й метадані до листа можна методами tag та metadata:
/**
* Get the mail representation of the notification.
*/
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 Message перед надсиланням повідомлення. Це дає вам змогу глибоко налаштувати повідомлення перед доставкою:
use Symfony\Component\Mime\Email;
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->withSymfonyMessage(function (Email $message) {
$message->getHeaders()->addTextHeader(
'Custom-Header', 'Header Value'
);
});
}
Використання mailable-класів
За потреби ви можете повернути з методу toMail свого сповіщення повноцінний mailable-об'єкт. Коли ви повертаєте Mailable замість MailMessage, вам потрібно вказати отримувача методом to mailable-об'єкта:
use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Mail\Mailable;
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): Mailable
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email);
}
Mailable-класи та сповіщення на льоту
Якщо ви надсилаєте сповіщення на льоту, екземпляр $notifiable, переданий методу toMail, буде екземпляром Illuminate\Notifications\AnonymousNotifiable, який пропонує метод routeNotificationFor для отримання адреси, на яку слід надіслати сповіщення:
use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Mail\Mailable;
/**
* Get the mail representation of the notification.
*/
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 команди Artisan make:notification:
php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
Як і всі інші поштові сповіщення, сповіщення з Markdown-шаблонами мають описувати у своєму класі метод toMail. Проте замість методів line та action для побудови сповіщення скористайтеся методом markdown, щоб указати назву Markdown-шаблону. Масив даних, які ви хочете зробити доступними шаблону, можна передати другим аргументом методу:
/**
* Get the mail representation of the notification.
*/
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>
Не робіть зайвих відступів, коли пишете Markdown-листи. За стандартами Markdown парсери рендерять вміст із відступами як блоки коду.
Компонент button
Компонент button рендерить відцентроване посилання-кнопку. Компонент приймає два аргументи: url та необов'язковий color. Підтримувані кольори - primary, green та red. Ви можете додати до сповіщення скільки завгодно компонентів button:
<x-mail::button :url="$url" color="green">
View Invoice
</x-mail::button>
Компонент panel
Компонент panel рендерить заданий блок тексту в панелі, колір тла якої трохи відрізняється від решти сповіщення. Це дозволяє привернути увагу до певного блоку тексту:
<x-mail::panel>
This is the panel content.
</x-mail::panel>
Компонент table
Компонент 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 до власного застосунку, щоб їх налаштувати. Щоб експортувати компоненти, опублікуйте тег ресурсів laravel-mail командою Artisan vendor:publish:
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 у цьому файлі, і ваші стилі автоматично буде вбудовано в HTML-представлення ваших Markdown-сповіщень.
Якщо ви хочете створити цілком нову тему для компонентів Markdown у Laravel, покладіть CSS-файл у каталог html/themes. Назвавши й зберігши свій CSS-файл, оновіть опцію theme у файлі конфігурації mail відповідно до назви нової теми.
Щоб змінити тему для окремого сповіщення, викличте метод theme під час побудови його поштового повідомлення. Метод theme приймає назву теми, яку слід використати під час надсилання сповіщення:
/**
* Get the mail representation of the notification.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->theme('invoice')
->subject('Invoice Paid')
->markdown('mail.invoice.paid', ['url' => $url]);
}
Сповіщення в базі даних
Передумови
Канал сповіщень database зберігає інформацію про сповіщення в таблиці бази даних. Ця таблиця міститиме тип сповіщення, а також JSON-структуру даних, яка його описує.
Ви можете робити запити до цієї таблиці, щоб показувати сповіщення в інтерфейсі вашого застосунку. Проте спершу вам потрібно створити таблицю, яка їх зберігатиме. Скористайтеся командою make:notifications-table, щоб згенерувати міграцію з належною схемою таблиці:
php artisan make:notifications-table
php artisan migrate
Якщо ваші моделі-отримувачі використовують первинні ключі UUID чи ULID, замініть у міграції таблиці сповіщень метод
morphsна uuidMorphs або ulidMorphs.
Форматування сповіщень у базі даних
Якщо сповіщення можна зберігати в таблиці бази даних, опишіть у класі сповіщення метод toDatabase або toArray. Цей метод отримає сутність $notifiable і має повернути звичайний PHP-масив. Повернений масив буде закодовано в JSON і збережено у стовпці data вашої таблиці notifications. Погляньмо на приклад методу toArray:
/**
* Get the array representation of the notification.
*
* @return array<string, mixed>
*/
public function toArray(object $notifiable): array
{
return [
'invoice_id' => $this->invoice->id,
'amount' => $this->invoice->amount,
];
}
Коли сповіщення збережено в базі вашого застосунку, стовпцю type за замовчуванням присвоюється назва класу сповіщення, а стовпець read_at матиме значення null. Проте ви можете змінити цю поведінку, описавши у класі сповіщення методи databaseType та initialDatabaseReadAtValue:
use Illuminate\Support\Carbon;
/**
* Get the notification's database type.
*/
public function databaseType(object $notifiable): string
{
return 'invoice-paid';
}
/**
* Get the initial value for the "read_at" column.
*/
public function initialDatabaseReadAtValue(): ?Carbon
{
return null;
}
toDatabase проти toArray
Метод toArray використовує й канал broadcast, щоб визначити, які дані надсилати вашому фронтенду на JavaScript. Якщо ви хочете мати два різні масиви для каналів database і broadcast, опишіть метод toDatabase замість toArray.
Доступ до сповіщень
Щойно сповіщення зберігаються в базі, вам потрібен зручний спосіб звертатися до них із ваших сутностей-отримувачів. Трейт Illuminate\Notifications\Notifiable, який підключено до стандартної моделі App\Models\User у Laravel, містить зв'язок Eloquent notifications, що повертає сповіщення сутності. Щоб дістати сповіщення, звертайтеся до цього методу як до будь-якого іншого зв'язку 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;
}
Якщо ви хочете дістати лише «прочитані» сповіщення, скористайтеся зв'язком readNotifications:
$user = App\Models\User::find(1);
foreach ($user->readNotifications 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 і надіслано вашому фронтенду. Погляньмо на приклад методу toBroadcast:
use Illuminate\Notifications\Messages\BroadcastMessage;
/**
* Get the broadcastable representation of the notification.
*/
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:
/**
* Get the type of the notification being broadcast.
*/
public function broadcastType(): string
{
return 'broadcast.message';
}
Прослуховування сповіщень
Сповіщення надсилаються в приватний канал, назва якого будується за домовленістю {notifiable}.{id}. Тож, якщо ви надсилаєте сповіщення екземпляру App\Models\User з ID 1, сповіщення буде надіслано в приватний канал App.Models.User.1. Користуючись Laravel Echo, ви можете легко слухати сповіщення в каналі методом notification:
Echo.private('App.Models.User.' + userId)
.notification((notification) => {
console.log(notification.type);
});
Використання React, Vue чи Svelte
Laravel Echo містить хуки для React, Vue та Svelte, які роблять прослуховування сповіщень безболісним. Для початку викличте хук useEchoNotification, який слухає сповіщення. Хук useEchoNotification автоматично виходить з каналів, коли компонент, який його використовує, демонтується:
import { useEchoNotification } from "@laravel/echo-react";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
);
<script setup lang="ts">
import { useEchoNotification } from "@laravel/echo-vue";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
);
</script>
<script>
import { useEchoNotification } from "@laravel/echo-svelte";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
);
</script>
За замовчуванням хук слухає всі сповіщення. Щоб указати типи сповіщень, які ви хочете слухати, передайте до useEchoNotification рядок або масив типів:
import { useEchoNotification } from "@laravel/echo-react";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
'App.Notifications.InvoicePaid',
);
<script setup lang="ts">
import { useEchoNotification } from "@laravel/echo-vue";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
'App.Notifications.InvoicePaid',
);
</script>
<script>
import { useEchoNotification } from "@laravel/echo-svelte";
useEchoNotification(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.type);
},
'App.Notifications.InvoicePaid',
);
</script>
Ви також можете описати форму даних сповіщення, отримавши кращу типобезпеку й зручність редагування:
type InvoicePaidNotification = {
invoice_id: number;
created_at: string;
};
useEchoNotification<InvoicePaidNotification>(
`App.Models.User.${userId}`,
(notification) => {
console.log(notification.invoice_id);
console.log(notification.created_at);
console.log(notification.type);
},
'App.Notifications.InvoicePaid',
);
Налаштування каналу сповіщень
Якщо ви хочете змінити канал, у який надсилаються сповіщення бродкастингу для сутності, опишіть у цій сутності метод 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;
/**
* The channels the user receives notification broadcasts on.
*/
public function receivesBroadcastNotificationsOn(): string
{
return 'users.'.$this->id;
}
}
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\VonageMessage:
use Illuminate\Notifications\Messages\VonageMessage;
/**
* Get the Vonage / SMS representation of the notification.
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content('Your SMS message content');
}
Вміст у Unicode
Якщо ваше SMS міститиме символи Unicode, викличте метод unicode під час створення екземпляра VonageMessage:
use Illuminate\Notifications\Messages\VonageMessage;
/**
* Get the Vonage / SMS representation of the notification.
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content('Your unicode message')
->unicode();
}
Налаштування номера «From»
Якщо ви хочете надсилати деякі сповіщення з номера, відмінного від указаного змінною середовища VONAGE_SMS_FROM, викличте метод from на екземплярі VonageMessage:
use Illuminate\Notifications\Messages\VonageMessage;
/**
* Get the Vonage / SMS representation of the notification.
*/
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content('Your SMS message content')
->from('15554443333');
}
Додавання клієнтського посилання
Якщо ви хочете відстежувати витрати за користувачем, командою чи клієнтом, додайте до сповіщення «клієнтське посилання». Vonage дозволить будувати звіти за цим посиланням, щоб ви краще розуміли, скільки SMS витрачає конкретний клієнт. Клієнтське посилання може бути будь-яким рядком до 40 символів:
use Illuminate\Notifications\Messages\VonageMessage;
/**
* Get the Vonage / SMS representation of the notification.
*/
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;
/**
* Route notifications for the Vonage channel.
*/
public function routeNotificationForVonage(Notification $notification): string
{
return $this->phone_number;
}
}
Сповіщення в Slack
Передумови
Перш ніж надсилати сповіщення в Slack, встановіть канал сповіщень Slack через Composer:
composer require laravel/slack-notification-channel
Крім того, вам потрібно створити застосунок Slack для свого робочого простору Slack.
Якщо вам треба надсилати сповіщення лише до того робочого простору, у якому створено застосунок, переконайтеся, що ваш застосунок має скопи chat:write, chat:write.public та chat:write.customize. Ці скопи додаються на вкладці керування застосунком «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. Розповсюдженням керують на вкладці «Manage Distribution» вашого застосунку в Slack. Щойно застосунок розповсюджено, ви можете скористатися Socialite, щоб отримувати бот-токени Slack від імені користувачів вашого застосунку.
Форматування сповіщень Slack
Якщо сповіщення можна надсилати як повідомлення Slack, опишіть у класі сповіщення метод toSlack. Цей метод отримає сутність $notifiable і має повернути екземпляр Illuminate\Notifications\Slack\SlackMessage. Ви можете будувати насичені сповіщення за допомогою Block Kit API від Slack. Приклад нижче можна переглянути в конструкторі Block Kit від Slack:
use Illuminate\Notifications\Slack\BlockKit\Blocks\ContextBlock;
use Illuminate\Notifications\Slack\BlockKit\Blocks\SectionBlock;
use Illuminate\Notifications\Slack\SlackMessage;
/**
* Get the Slack representation of the notification.
*/
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
Замість плавних методів побудови повідомлення ви можете передати сирі JSON-дані, згенеровані конструктором Block Kit від 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, який натиснув кнопку, ID натиснутої кнопки тощо. Далі ваш застосунок може визначити, яку дію виконати, на основі цих даних. Вам також слід перевіряти, що запит справді надійшов від 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;
/**
* Get the Slack representation of the notification.
*/
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;
/**
* Get the Slack representation of the notification.
*/
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');
}
);
});
}
Огляд блоків Slack
Якщо ви хочете швидко оглянути блоки, які будуєте, викличте метод dd на екземплярі SlackMessage. Метод dd згенерує й виведе URL до конструктора Block Kit від Slack, який покаже попередній перегляд даних і сповіщення у вашому браузері. Ви можете передати методу dd значення true, щоб вивести сирі дані:
return (new SlackMessage)
->text('One of your invoices has been paid!')
->headerBlock('Invoice Paid')
->dd();
Маршрутизація сповіщень Slack
Щоб спрямувати сповіщення Slack до потрібної команди й каналу, опишіть у своїй моделі-отримувачі метод routeNotificationForSlack. Цей метод може повернути одне з трьох значень:
null- тоді маршрутизацію віддано каналу, налаштованому в самому сповіщенні. Ви можете скористатися методомtoпід час побудовиSlackMessage, щоб налаштувати канал у сповіщенні.- Рядок із каналом Slack, до якого слід надіслати сповіщення, наприклад
#support-channel. - Екземпляр
SlackRoute, який дозволяє вказати OAuth-токен і назву каналу, наприкладSlackRoute::make($this->slack_channel, $this->slack_token). Цей спосіб слід використовувати для надсилання сповіщень до зовнішніх робочих просторів.
Наприклад, якщо метод routeNotificationForSlack поверне #support-channel, сповіщення буде надіслано в канал #support-channel того робочого простору, який пов'язано з токеном Bot User OAuth із файлу 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;
/**
* Route notifications for the Slack channel.
*/
public function routeNotificationForSlack(Notification $notification): mixed
{
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;
/**
* Route notifications for the Slack channel.
*/
public function routeNotificationForSlack(Notification $notification): mixed
{
return SlackRoute::make($this->slack_channel, $this->slack_token);
}
}
Локалізація сповіщень
Laravel дозволяє надсилати сповіщення в локалі, відмінній від поточної локалі HTTP-запиту, і навіть запам'ятає цю локаль, якщо сповіщення поставлено в чергу.
Для цього клас 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
{
/**
* Get the user's preferred locale.
*/
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();
// Perform order shipping...
// Assert that no notifications were sent...
Notification::assertNothingSent();
// Assert a notification was sent to the given users...
Notification::assertSentTo(
[$user], OrderShipped::class
);
// Assert a notification was not sent...
Notification::assertNotSentTo(
[$user], AnotherNotification::class
);
// Assert a notification was sent twice...
Notification::assertSentTimes(WeeklyReminder::class, 2);
// Assert that a given number of notifications were sent...
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();
// Perform order shipping...
// Assert that no notifications were sent...
Notification::assertNothingSent();
// Assert a notification was sent to the given users...
Notification::assertSentTo(
[$user], OrderShipped::class
);
// Assert a notification was not sent...
Notification::assertNotSentTo(
[$user], AnotherNotification::class
);
// Assert a notification was sent twice...
Notification::assertSentTimes(WeeklyReminder::class, 2);
// Assert that a given number of notifications were sent...
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 event.
*/
public function handle(NotificationSending $event): void
{
// ...
}
}
Сповіщення не буде надіслано, якщо слухач події NotificationSending поверне зі свого методу handle значення false:
/**
* Handle the event.
*/
public function handle(NotificationSending $event): bool
{
return false;
}
Усередині слухача ви можете звернутися до властивостей події notifiable, notification і channel, щоб дізнатися більше про отримувача сповіщення чи саме сповіщення:
/**
* Handle the event.
*/
public function handle(NotificationSending $event): void
{
// $event->channel
// $event->notifiable
// $event->notification
}
Подія надісланого сповіщення
Коли сповіщення надіслано, система сповіщень диспетчеризує подію Illuminate\Notifications\Events\NotificationSent. Вона містить сутність-отримувача та сам екземпляр сповіщення. Ви можете створити слухачів подій для цієї події у своєму застосунку:
use Illuminate\Notifications\Events\NotificationSent;
class LogNotification
{
/**
* Handle the event.
*/
public function handle(NotificationSent $event): void
{
// ...
}
}
Усередині слухача ви можете звернутися до властивостей події notifiable, notification, channel та response, щоб дізнатися більше про отримувача сповіщення чи саме сповіщення:
/**
* Handle the event.
*/
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
{
/**
* Send the given notification.
*/
public function send(object $notifiable, Notification $notification): void
{
$message = $notification->toVoice($notifiable);
// Send notification to the $notifiable instance...
}
}
Щойно клас вашого каналу сповіщень описано, ви можете повертати його назву з методу 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;
/**
* Get the notification channels.
*/
public function via(object $notifiable): string
{
return VoiceChannel::class;
}
/**
* Get the voice representation of the notification.
*/
public function toVoice(object $notifiable): VoiceMessage
{
// ...
}
}