Сповіщення · Laravel
Частину підрозділів ще не перекладено, вони показані англійською нижче в тексті або лишились в оригіналі. Готові фрагменти вже перевірені редактором.
Вступ
Крім надсилання пошти, Laravel умієнадсилати сповіщення різними каналами доставки: email, SMS (через Vonage, раніше відомий як Nexmo) і Slack. Додатково спільнота створила десятки каналів сповіщень для найрізноманітніших сервісів. Сповіщення також можна зберігати в базі даних, щоб показувати їх у вебінтерфейсі.
Зазвичай сповіщення - це короткі інформаційні повідомлення про те, що сталося у вашому застосунку. Наприклад, у білінговому застосунку ви можете надсилати користувачам сповіщення «Invoice Paid» каналами email і 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));
[!NOTE] Пам'ятайте, що трейт
Notifiableможна використовувати в будь-якій вашій моделі. Ви не обмежені лише моделлюUser.
Використання фасаду Notification
Як альтернатива, сповіщення можна надсилати через фасад Notification. Цей підхід зручний, коли потрібно надіслати сповіщення кільком notifiable-сутностям, наприклад колекції користувачів. Щоб надіслати сповіщення через фасад, передайте всі notifiable-сутності та екземпляр сповіщення в метод 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.
[!NOTE] Якщо ви хочете використовувати інші канали доставки, наприклад 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'];
}
Сповіщення в чергах
[!WARNING] Перед тим як ставити сповіщення в черги, налаштуйте чергу і запустіть обробник.
Надсилання сповіщень може займати час, особливо якщо канал має звернутися до зовнішнього 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 має повертати масив назв каналів і значень затримки:
/**
* Визначити затримку доставки сповіщення.
*
* @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;
/**
* Створити новий екземпляр сповіщення.
*/
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',
];
}
Налаштування атрибутів завдання для сповіщення в черзі
Поведінку завдання в черзі, що стоїть за сповіщенням, можна налаштувати, визначивши атрибути черги на класі сповіщення. Ці атрибути успадкує завдання (job), яке надсилає сповіщення:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Queue\Attributes\FailOnTimeout;
use Illuminate\Queue\Attributes\MaxExceptions;
use Illuminate\Queue\Attributes\Timeout;
use Illuminate\Queue\Attributes\Tries;
#[Tries(5)]
#[Timeout(120)]
#[MaxExceptions(3)]
#[FailOnTimeout]
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;
/**
* Обчислити кількість секунд очікування перед повторною спробою сповіщення.
*/
public function backoff(): int
{
return 3;
}
/**
* Визначити час, після якого сповіщення має вважатися прострокованим.
*/
public function retryUntil(): DateTime
{
return now()->plus(minutes: 5);
}
[!NOTE] Більше про ці атрибути та методи завдань читайте в документації про завдання в чергах.
Middleware для сповіщень у чергах
Сповіщення в чергах можуть визначати middleware так само, як завдання в чергах. Для початку визначте метод middleware на класі сповіщення. Метод middleware отримує змінні $notifiable і $channel, завдяки яким ви можете підбирати middleware залежно від призначення сповіщення:
use Illuminate\Queue\Middleware\RateLimited;
/**
* Отримати middleware, через які має пройти завдання сповіщення.
*
* @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;
/**
* Створити новий екземпляр сповіщення.
*/
public function __construct()
{
$this->afterCommit();
}
}
[!NOTE] Щоб дізнатися більше про способи обійти ці проблеми, перегляньте документацію про завдання в чергах і транзакції бази даних.
Визначення, чи треба надсилати сповіщення з черги
Після того як сповіщення відправлено в чергу для фонової обробки, його зазвичай підхоплює обробник черги й надсилає призначеному отримувачу.
Проте, якщо ви хочете остаточно вирішувати, чи надсилати сповіщення вже під час обробки обробником черги, визначте на класі сповіщення метод shouldSend. Якщо цей метод повертає false, сповіщення не буде надіслано:
/**
* Визначити, чи треба надсилати сповіщення.
*/
public function shouldSend(object $notifiable, string $channel): bool
{
return $this->invoice->isPaid();
}
Після надсилання сповіщень
Якщо ви хочете виконати код після того, як сповіщення надіслано, визначте на класі сповіщення метод afterSending. Цей метод отримає notifiable-сутність, назву каналу і відповідь від каналу:
/**
* Обробити сповіщення після його надсилання.
*/
public function afterSending(object $notifiable, string $channel, mixed $response): void
{
// ...
}
Сповіщення на вимогу
Іноді потрібно надіслати сповіщення тому, хто не зберігається як «користувач» вашого застосунку. За допомогою методу route фасаду Notification ви можете задати ad-hoc інформацію про маршрутизацію сповіщення перед його надсиланням:
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 ви хочете вказати ім'я отримувача, передайте масив, де першим елементом буде пара «email-адреса як ключ, ім'я як значення»:
Notification::route('mail', [
'barrett@example.com' => 'Barrett Blair',
])->notify(new InvoicePaid($invoice));
Метод routes дозволяє задати ad-hoc маршрутизацію одразу для кількох каналів сповіщень:
Notification::routes([
'mail' => ['barrett@example.com' => 'Barrett Blair'],
'vonage' => '5555555555',
])->notify(new InvoicePaid($invoice));
Email-сповіщення
Форматування email-повідомлень
Якщо сповіщення можна надсилати як email, визначте на класі сповіщення метод toMail. Цей метод отримає notifiable-сутність $notifiable і має повертати екземпляр Illuminate\Notifications\Messages\MailMessage.
Клас MailMessage містить кілька простих методів, які допомагають будувати транзакційні email-повідомлення. Email-повідомлення можуть містити рядки тексту та «call to action». Погляньмо на приклад методу toMail:
/**
* Отримати email-представлення сповіщення.
*/
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!');
}
[!NOTE] Зверніть увагу: у методі
toMailми використовуємо$this->invoice->id. Будь-які дані, потрібні сповіщенню для формування повідомлення, можна передати в його конструктор.
У цьому прикладі ми реєструємо привітання, рядок тексту, call to action і ще один рядок тексту. Ці методи обʼєкта MailMessage роблять форматування невеликих транзакційних листів простим і швидким. Далі канал mail перетворить компоненти повідомлення на гарний адаптивний HTML-шаблон листа з текстовою версією. Ось приклад листа, згенерованого каналом mail:
[!NOTE] Надсилаючи email-сповіщення, обовʼязково задайте опцію конфігурації
nameу файліconfig/app.php. Це значення використовуватиметься у верхньому та нижньому колонтитулах ваших email-сповіщень.
Повідомлення про помилки
Частина сповіщень інформує користувачів про помилки, наприклад про невдалу оплату рахунку. Щоб позначити, що email-повідомлення стосується помилки, викличте метод error під час побудови повідомлення. З методом error кнопка call to action буде червоною замість чорної:
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->error()
->subject('Invoice Payment Failed')
->line('...');
}
Інші способи форматування email-сповіщень
Замість оголошення «рядків» тексту в класі сповіщення ви можете скористатися методом view, щоб указати власний шаблон для рендерингу листа сповіщення:
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->view(
'mail.invoice.paid', ['invoice' => $this->invoice]
);
}
Текстове представлення (view) для email-повідомлення можна задати, передавши назву представлення другим елементом масиву, який передається в метод view:
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->view(
['mail.invoice.paid', 'mail.invoice.paid-text'],
['invoice' => $this->invoice]
);
}
Або, якщо ваше повідомлення має лише текстове представлення, скористайтеся методом text:
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)->text(
'mail.invoice.paid-text', ['invoice' => $this->invoice]
);
}
Налаштування відправника
За замовчуванням відправник листа (адреса from) визначається у файлі конфігурації config/mail.php. Проте адресу from для конкретного сповіщення можна задати методом from:
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->from('barrett@example.com', 'Barrett Blair')
->line('...');
}
Налаштування отримувача
Надсилаючи сповіщення каналом mail, система сповіщень автоматично шукає властивість email у вашій notifiable-сутності. Ви можете задати, яка email-адреса використовується для доставки сповіщення, визначивши метод routeNotificationForMail на notifiable-сутності:
<?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;
/**
* Маршрутизація сповіщень для каналу mail.
*
* @return array<string, string>|string
*/
public function routeNotificationForMail(Notification $notification): array|string
{
// Повернути лише email-адресу...
return $this->email_address;
// Повернути email-адресу та імʼя...
return [$this->email_address => $this->name];
}
}
Налаштування теми листа
За замовчуванням темою листа є назва класу сповіщення, відформатована в «Title Case». Тож якщо ваш клас сповіщення називається InvoicePaid, темою листа буде Invoice Paid. Якщо ви хочете задати іншу тему, викличте метод subject під час побудови повідомлення:
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject('Notification Subject')
->line('...');
}
Налаштування mailer
За замовчуванням email-сповіщення надсилається через mailer, визначений у файлі конфігурації config/mail.php. Проте ви можете задати інший mailer під час виконання, викликавши метод mailer під час побудови повідомлення:
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->mailer('postmark')
->line('...');
}
Налаштування шаблонів
HTML- і текстовий шаблон, які використовують email-сповіщення, можна змінити, опублікувавши ресурси пакета сповіщень. Після виконання цієї команди шаблони email-сповіщень будуть у теці resources/views/vendor/notifications:
php artisan vendor:publish --tag=laravel-notifications
Вкладення
Щоб додати вкладення до email-сповіщення, використовуйте метод attach під час побудови повідомлення. Метод attach приймає абсолютний шлях до файлу першим аргументом:
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file');
}
[!NOTE] Метод
attach, який пропонують email-повідомлення сповіщень, також приймає attachable-обʼєкти. Щоб дізнатися більше, перегляньте повну документацію про attachable-обʼєкти.
Долучаючи файли до повідомлення, ви можете також задати відображуване імʼя та/або MIME-тип, передавши array другим аргументом методу attach:
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attach('/path/to/file', [
'as' => 'name.pdf',
'mime' => 'application/pdf',
]);
}
Коли потрібно, до повідомлення можна долучити кілька файлів методом attachMany:
/**
* Отримати email-представлення сповіщення.
*/
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;
/**
* Отримати email-представлення сповіщення.
*/
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, укажіть імʼя файлу, яке має отримати вкладення:
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->greeting('Hello!')
->attachData($this->pdf, 'name.pdf', [
'mime' => 'application/pdf',
]);
}
Додавання теґів і метаданих
Деякі сторонні email-провайдери, як-от Mailgun і Postmark, підтримують «теґи» й «метадані» повідомлень, за якими можна групувати й відслідковувати надіслані вашим застосунком листи. Додати теґи й метадані до email-повідомлення можна методами tag і metadata:
/**
* Отримати email-представлення сповіщення.
*/
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 Message
Метод withSymfonyMessage класу MailMessage дозволяє зареєструвати замикання, яке буде викликано з екземпляром Symfony Message перед надсиланням повідомлення. Це дає можливість глибоко налаштувати повідомлення перед доставкою:
use Symfony\Component\Mime\Email;
/**
* Отримати email-представлення сповіщення.
*/
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;
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): Mailable
{
return (new InvoicePaidMailable($this->invoice))
->to($notifiable->email);
}
Mailable-класи і сповіщення на вимогу
Якщо ви надсилаєте сповіщення на вимогу, екземпляр $notifiable, переданий у метод toMail, буде екземпляром Illuminate\Notifications\AnonymousNotifiable, який має метод routeNotificationFor для отримання email-адреси, куди слід надіслати сповіщення на вимогу:
use App\Mail\InvoicePaid as InvoicePaidMailable;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Mail\Mailable;
/**
* Отримати email-представлення сповіщення.
*/
public function toMail(object $notifiable): Mailable
{
$address = $notifiable instanceof AnonymousNotifiable
? $notifiable->routeNotificationFor('mail')
: $notifiable->email;
return (new InvoicePaidMailable($this->invoice))
->to($address);
}
Попередній перегляд email-сповіщень
Проєктуючи шаблон email-сповіщення, зручно швидко переглядати відрендерене повідомлення в браузері, як звичайний Blade-шаблон. Тому Laravel дозволяє повертати будь-яке email-повідомлення, згенероване email-сповіщенням, безпосередньо із замикання маршруту або контролера. Коли повертається 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-сповіщення поштою дають змогу скористатися готовими шаблонами email-сповіщень, залишаючи більше свободи для написання довших, індивідуальних повідомлень. Оскільки повідомлення написані в Markdown, Laravel може відрендерити гарні адаптивні HTML-шаблони, автоматично згенерувавши до них текстову версію.
Генерація повідомлення
Щоб згенерувати сповіщення разом із відповідним Markdown-шаблоном, скористайтеся опцією --markdown Artisan-команди make:notification:
php artisan make:notification InvoicePaid --markdown=mail.invoice.paid
Як і всі інші email-сповіщення, сповіщення з Markdown-шаблонами мають визначати метод toMail на своєму класі. Проте замість методів line і action для побудови сповіщення використовуйте метод markdown, щоб указати назву Markdown-шаблону. Масив даних, які ви хочете зробити доступними в шаблоні, можна передати другим аргументом методу:
/**
* Отримати email-представлення сповіщення.
*/
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>
[!NOTE] Не робіть надмірних відступів, коли пишете 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-компоненти сповіщень у власний застосунок, щоб їх налаштувати. Для експорту скористайтеся Artisan-командою vendor:publish і опублікуйте теґ ресурсів 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 у цьому файлі, і ваші стилі автоматично будуть вбудовані (in-lined) у HTML-представлення ваших Markdown-сповіщень.
Якщо ви хочете створити цілком нову тему для Markdown-компонентів Laravel, покладіть CSS-файл у теку html/themes. Після того як ви назвете й збережете свій CSS-файл, оновіть опцію theme у файлі конфігурації mail, щоб вона відповідала назві нової теми.
Щоб задати тему для окремого сповіщення, викличте метод theme під час побудови email-повідомлення сповіщення. Метод theme приймає назву теми, яку слід використати під час надсилання сповіщення:
/**
* Отримати email-представлення сповіщення.
*/
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
[!NOTE] Якщо ваші notifiable-моделі використовують первинні ключі UUID або ULID, у міграції таблиці сповіщень замініть метод
morphsна uuidMorphs або ulidMorphs.
Форматування сповіщень у базі даних
Якщо сповіщення можна зберігати в таблиці бази даних, визначте на класі сповіщення метод toDatabase або toArray. Цей метод отримає notifiable-сутність $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 за замовчуванням отримує назву класу сповіщення, а стовпець read_at буде null. Проте цю поведінку можна змінити, визначивши в класі сповіщення методи databaseType та initialDatabaseReadAtValue:
use Illuminate\Support\Carbon;
/**
* Отримати тип сповіщення для бази даних.
*/
public function databaseType(object $notifiable): string
{
return 'invoice-paid';
}
/**
* Отримати початкове значення для стовпця "read_at".
*/
public function initialDatabaseReadAtValue(): ?Carbon
{
return null;
}
toDatabase проти toArray
Метод toArray також використовує канал broadcast, щоб визначити, які дані транслювати у ваш фронтенд на JavaScript. Якщо ви хочете мати два різні представлення у вигляді масиву для каналів database і broadcast, визначте метод toDatabase замість toArray.
Доступ до сповіщень
Коли сповіщення збережені в базі даних, потрібен зручний спосіб отримувати їх із ваших notifiable-сутностей. Трейт Illuminate\Notifications\Notifiable, підключений до стандартної моделі Laravel App\Models\User, містить звʼязок 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;
}
[!NOTE] Щоб звертатися до сповіщень із JavaScript-клієнта, визначте у своєму застосунку контролер сповіщень, який повертає сповіщення для notifiable-сутності, наприклад для поточного користувача. Далі робіть 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();
Broadcast-сповіщення
Передумови
Перед трансляцією сповіщень налаштуйте й вивчіть сервіси трансляції подій Laravel. Трансляція подій дає спосіб реагувати на серверні події Laravel з фронтенду на JavaScript.
Форматування broadcast-сповіщень
Канал broadcast транслює сповіщення за допомогою сервісів трансляції подій Laravel, що дозволяє фронтенду на JavaScript ловити сповіщення в реальному часі. Якщо сповіщення підтримує трансляцію, визначте на його класі метод toBroadcast. Цей метод отримає notifiable-сутність $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,
]);
}
Broadcast Notifications - Broadcast Queue Configuration, Customizing the Notification Type, Listening for Notifications; SMS Notifications - Prerequisites, Formatting SMS Notifications, Unicode Content, Customizing the "From" Number, Adding a Client Reference, Routing SMS Notifications; Slack Notifications - Prerequisites, Formatting Slack Notifications, Slack Interactivity, Routing Slack Notifications, Notifying External Slack Workspaces; Localizing Notifications; Testing; Notification Events; Custom Channels.
Перекладаємо з офіційної документації, розділ за розділом, і не ховаємо недоперекладене. Помітили неточність у терміні чи реченні: напишіть, виправимо.