Уведомления — это как нервная система приложения: без них пользователь не узнает о важных событиях, а вы потеряете вовлечённость. В Yii2 есть всё необходимое, чтобы построить удобную и масштабируемую систему оповещений. В этой статье мы разберём, как это сделать правильно, с примерами кода и практическими советами.
Зачем вообще нужна система уведомлений?
Представьте: пользователь оформил заказ, но не получил подтверждение. Или забыл пароль, а письмо не пришло. Без уведомлений продукт кажется «мёртвым». Хорошая система оповещений решает три задачи:
- Информирует о событиях (заказ, регистрация, смена статуса).
- Повышает вовлечённость (напоминания, акции).
- Снижает нагрузку на поддержку (автоматические ответы).
В Yii2 можно быстро организовать отправку email, SMS, push-уведомлений и даже сообщений в мессенджеры. Главное — не разбрасывать код по проекту, а сделать единый сервис.
Архитектура: как всё устроить
Самый простой путь — использовать встроенный компонент mailer. Но если у вас несколько типов уведомлений и каналов доставки, лучше сразу заложить гибкую структуру. Предлагаю такой подход:
- Модель уведомления — хранит шаблон, канал, получателя и статус.
- Сервис уведомлений — центральный класс, который принимает событие и решает, куда и что отправить.
- Очередь — для асинхронной отправки, чтобы не тормозить запросы.
Начнём с миграции для таблицы уведомлений. Вот пример:
use yii\db\Migration;
class m240101_000000_create_notification_table extends Migration
{
public function safeUp()
{
$this->createTable('{{%notification}}', [
'id' => $this->primaryKey(),
'user_id' => $this->integer()->notNull(),
'channel' => $this->string(20)->notNull(), // email, sms, push
'subject' => $this->string(),
'body' => $this->text(),
'status' => $this->string(20)->defaultValue('pending'),
'created_at' => $this->integer(),
'sent_at' => $this->integer(),
]);
$this->createIndex('idx-notification-user', '{{%notification}}', 'user_id');
}
public function safeDown()
{
$this->dropTable('{{%notification}}');
}
}
Теперь создадим модель Notification через Gii или вручную. Не забудьте прописать правила валидации и связи.
Сервис уведомлений: центральный мозг
Создайте компонент NotificationService в папке components или services. Он будет принимать событие и решать, какой канал использовать. Вот упрощённый пример:
namespace app\components;
use app\models\Notification;
use Yii;
class NotificationService
{
public function send($userId, $channel, $subject, $body)
{
$notification = new Notification();
$notification->user_id = $userId;
$notification->channel = $channel;
$notification->subject = $subject;
$notification->body = $body;
$notification->status = 'pending';
$notification->created_at = time();
if (!$notification->save()) {
Yii::error('Не удалось сохранить уведомление: ' . json_encode($notification->errors));
return false;
}
// Отправляем в зависимости от канала
switch ($channel) {
case 'email':
return $this->sendEmail($notification);
case 'sms':
return $this->sendSms($notification);
default:
Yii::warning("Неизвестный канал: $channel");
return false;
}
}
private function sendEmail($notification)
{
$user = $notification->user; // предполагаем связь
return Yii::$app->mailer->compose()
->setTo($user->email)
->setSubject($notification->subject)
->setTextBody($notification->body)
->send();
}
private function sendSms($notification)
{
// Здесь интеграция с SMS-шлюзом
return true;
}
}
Обратите внимание: сервис сохраняет уведомление перед отправкой. Если отправка не удалась, статус останется pending, и вы сможете повторить попытку позже.
Очереди — для скорости и надёжности
Отправка email или SMS может занимать секунды. Если делать это синхронно, пользователь будет ждать. Лучше использовать очереди. В Yii2 есть компонент queue (требует установки пакета yiisoft/yii2-queue). Настроим его в конфиге:
// config/web.php
return [
'components' => [
'queue' => [
'class' => \yii\queue\db\Queue::class,
'channel' => 'queue',
],
// ...
],
];
Затем создадим задачу для отправки уведомления:
namespace app\jobs;
use app\models\Notification;
use yii\base\BaseObject;
use yii\queue\JobInterface;
class SendNotificationJob extends BaseObject implements JobInterface
{
public $notificationId;
public function execute($queue)
{
$notification = Notification::findOne($this->notificationId);
if (!$notification) {
return;
}
// Логика отправки в зависимости от канала
// ...
$notification->status = 'sent';
$notification->sent_at = time();
$notification->save(false);
}
}
И запускаем задачу из сервиса:
Yii::$app->queue->push(new SendNotificationJob([
'notificationId' => $notification->id,
]));
Шаблоны и персонализация
Чтобы не писать HTML в каждом уведомлении, используйте шаблоны. В Yii2 есть компонент view, который умеет рендерить файлы. Создайте папку views/notifications и файлы вроде order-confirmation.php:
// views/notifications/order-confirmation.php
use yii\helpers\Html;
/** @var $user \app\models\User */
/** @var $order \app\models\Order */
?>
Здравствуйте, = Html::encode($user->name) ?>!
Ваш заказ №= $order->id ?> подтверждён.
Сумма: = Yii::$app->formatter->asCurrency($order->total) ?>
В сервисе рендерите шаблон и сохраняйте готовый HTML в тело уведомления:
$body = Yii::$app->view->render('@app/views/notifications/order-confirmation', [
'user' => $user,
'order' => $order,
]);
$service->send($user->id, 'email', 'Заказ оформлен', $body);
Такой подход упрощает поддержку: изменили шаблон — и все новые уведомления используют новый дизайн.
Сравнение каналов доставки
Выбор канала зависит от срочности и типа события. Вот таблица для ориентира:
| Канал | Скорость | Стоимость | Когда использовать |
|---|---|---|---|
| Средняя | Низкая | Подтверждения, маркетинг, отчёты | |
| SMS | Высокая | Средняя | Срочные коды, оповещения о безопасности |
| Push | Мгновенная | Низкая | Мобильные приложения, акции |
Комбинируйте каналы: например, для важных событий отправляйте и email, и push. Но не спамьте — пользователи это не любят.
Что в итоге?
Мы построили основу системы уведомлений на Yii2: модель, сервис, очередь и шаблоны. Такой подход даёт гибкость и масштабируемость. Вы можете добавлять новые каналы, не меняя логику ядра. Главное — не забывайте про логирование и повторные попытки при сбоях.
Начните с простого email-уведомления, а затем постепенно расширяйте функционал. Удачи в разработке!

