Питання на співбесіді: Notifications
Найпопулярніші питання з реальних Laravel/PHP співбесід для всіх рівнів
3 питання
Mailable - це лист. Notification - це повідомлення, яке може піти листом, у базу, в Slack чи кудись ще, і канал вибирається окремо від змісту.
Створення:
php artisan make:notification VacancyPublished
class VacancyPublished extends Notification
{
public function __construct(public Vacancy $vacancy)
{
}
public function via(object $notifiable): array
{
return ['mail', 'database'];
}
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject('Вашу вакансію опубліковано')
->line("«{$this->vacancy->title}» тепер видно всім.")
->action('Переглянути', route('vacancies.show', $this->vacancy));
}
/**
* @return array<string, mixed>
*/
public function toArray(object $notifiable): array
{
return ['vacancy_id' => $this->vacancy->id];
}
}
Відправлення:
$user->notify(new VacancyPublished($vacancy));
// або багатьом
Notification::send($users, new VacancyPublished($vacancy));
Метод notify() доступний завдяки трейту Notifiable на моделі.
Що дає канал database: сповіщення зберігається в таблиці notifications, і з нього робиться «дзвіночок» в інтерфейсі - $user->unreadNotifications.
Коли достатньо Mailable: одноразовий лист без варіантів доставки - чек, звіт, підтвердження форми. Notification доречний, коли те саме повідомлення має йти різними каналами або користувач сам обирає, як його повідомляти.
Notification - одне повідомлення, яке можна доставити кількома каналами одночасно.
class InvoicePaid extends Notification
{
public function via(object $notifiable): array
{
return ['mail', 'database', 'broadcast'];
}
public function toMail($notifiable): MailMessage { /* ... */ }
public function toArray($notifiable): array { /* для database */ }
}
$user->notify(new InvoicePaid($invoice));
Канали з коробки: mail, database (зберігає в notifications), broadcast (WebSockets), Vonage (SMS), Slack. Є community-канали (Telegram, push). Канал database зручний для «дзвіночка» сповіщень у UI; реалізувавши ShouldQueue, відправку виносять у чергу.
Вбудованих каналів чотири - mail, database, broadcast, vonage. Усе інше - Slack, Telegram, SMS українського провайдера, пуші - або пакет, або власний канал.
Канал - це клас з одним методом:
class TelegramChannel
{
public function __construct(private TelegramClient $client)
{
}
public function send(object $notifiable, Notification $notification): void
{
$chatId = $notifiable->routeNotificationFor('telegram');
if ($chatId === null) {
return;
}
$this->client->sendMessage($chatId, $notification->toTelegram($notifiable));
}
}
Підключення в сповіщенні:
class VacancyPublished extends Notification
{
public function via(object $notifiable): array
{
return [TelegramChannel::class, 'mail'];
}
public function toTelegram(object $notifiable): string
{
return "Нова вакансія: {$this->vacancy->title}";
}
}
Куди слати - вирішує сам отримувач:
class User extends Authenticatable
{
public function routeNotificationForTelegram(): ?string
{
return $this->telegram_chat_id;
}
}
Навіщо це, а не просто виклик API. Сповіщення дає те, чого ручний виклик не має: один клас описує повідомлення для всіх каналів одразу, via() вирішує канали за налаштуваннями користувача, ShouldQueue відправляє асинхронно, а Notification::fake() дозволяє перевірити відправлення в тесті без мережі.