Система уведомлений WordPress: пошаговое руководство для разработчиков

white and blue printer paper

Введение

Уведомления – один из ключевых элементов пользовательского опыта. В WordPress они могут быть реализованы как in‑app оповещения, push‑уведомления или email‑рассылки. В этой статье мы построим универсальную систему уведомлений WordPress, охватив все уровни: хранение данных, API, фронтенд и отправку писем.

1. Проектирование базы данных уведомлений

Для масштабируемости рекомендуется использовать отдельную таблицу, а не кастомный тип записей. Это позволяет быстро фильтровать, удалять и индексировать данные.

1.1. Создание таблицы

function notif_create_table() { global $wpdb; $table_name = $wpdb->prefix. 'user_notifications'; $charset_collate = $wpdb->get_charset_collate(); $sql = "CREATE TABLE $table_name ( id BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT, user_id BIGINT(20) UNSIGNED NOT NULL, type VARCHAR(50) NOT NULL, title TEXT NOT NULL, message TEXT NOT NULL, is_read TINYINT(1) DEFAULT 0, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY user_id (user_id), KEY is_read (is_read) ) $charset_collate;"; require_once ABSPATH. 'wp-admin/includes/upgrade.php'; dbDelta( $sql ); } register_activation_hook( __FILE__, 'notif_create_table' );

Таблица wp_user_notifications хранит все сообщения, привязанные к ID пользователя.

1.2. CRUD‑операции

Ниже примеры функций для добавления и получения уведомлений.

function notif_add( $user_id, $type, $title, $message ) { global $wpdb; $table = $wpdb->prefix. 'user_notifications'; $wpdb->insert( $table, [ 'user_id' => $user_id, 'type' => sanitize_text_field( $type ), 'title' => wp_kses_post( $title ), 'message' => wp_kses_post( $message ), 'is_read' => 0, ] ); return $wpdb->insert_id; } function notif_get_unread( $user_id, $limit = 20 ) { global $wpdb; $table = $wpdb->prefix. 'user_notifications'; $sql = $wpdb->prepare( "SELECT * FROM $table WHERE user_id = %d AND is_read = 0 ORDER BY created_at DESC LIMIT %d", $user_id, $limit ); return $wpdb->get_results( $sql ); }

2. REST API для доступа к уведомлениям

WordPress предоставляет мощный WP_REST_Controller. Мы регистрируем два эндпоинта: получение списка и отметка как прочитанное.

2.1. Регистрация маршрутов

add_action( 'rest_api_init', function () { register_rest_route( 'notif/v1', '/unread', [ 'methods' => 'GET', 'callback' => 'notif_rest_get_unread', 'permission_callback' => function( $request ) { return is_user_logged_in(); }, ] ); register_rest_route( 'notif/v1', '/read/(?P<id>d+)', [ 'methods' => 'POST', 'callback' => 'notif_rest_mark_read', 'permission_callback' => function( $request ) { return is_user_logged_in(); }, ] ); } ); function notif_rest_get_unread( $request ) { $user_id = get_current_user_id(); $notifications = notif_get_unread( $user_id ); return rest_ensure_response( $notifications ); } function notif_rest_mark_read( $request ) { $id = (int) $request['id']; global $wpdb; $table = $wpdb->prefix. 'user_notifications'; $wpdb->update( $table, ['is_read' => 1], ['id' => $id, 'user_id' => get_current_user_id()] ); return rest_ensure_response( ['success' => true] ); }

Эти маршруты можно использовать в любом JS‑фреймворке или обычном jQuery.

3. Front‑end: in‑app уведомления

Для отображения уведомлений в админ‑панели и на клиентской части воспользуемся fetch и небольшим шаблоном.

3.1. HTML‑разметка

<div id="notif-container" class="notif‑wrapper"></div> <style>.notif‑wrapper { position: fixed; top: 80px; right: 20px; width: 300px; z-index: 9999; }.notif‑item { background:#fff; border:1px solid #ddd; padding:10px; margin-bottom:8px; box-shadow:0 2px 4px rgba(0,0,0,0.1); }.notif‑item.unread { border-left:4px solid #0073aa; } </style>

3.2. JavaScript‑логика

<script> document.addEventListener('DOMContentLoaded', function() { const container = document.getElementById('notif-container'); async function loadNotifications(){ const resp = await fetch('/wp-json/notif/v1/unread'); const data = await resp.json(); container.innerHTML = ''; data.forEach(n => { const el = document.createElement('div'); el.className = 'notif-item unread'; el.innerHTML = `${n.title}

${n.message}

`; el.addEventListener(‘click’, () => markAsRead(n.id, el)); container.appendChild(el); }); } async function markAsRead(id, el){ await fetch(`/wp-json/notif/v1/read/${id}`, {method:’POST’}); el.classList.remove(‘unread’); } loadNotifications(); // Автообновление каждые 60 сек. setInterval(loadNotifications, 60000); }); </script>

Не забудьте добавить скрипт в очередь через wp_enqueue_script. Также проверьте защиту от Drive‑by download, чтобы злоумышленники не смогли подменить ваш JS‑файл.

4. Email‑уведомления

Для критических событий (например, новый комментарий или успешный заказ) удобно отправлять письма.

4.1. Пример отправки через wp_mail

function notif_send_email( $user_id, $subject, $message ) { $user = get_user_by('ID', $user_id); if (! $user ||! $user->user_email ) return false; $headers = ['Content-Type: text/html; charset=UTF-8']; $body = wpautop( $message ); return wp_mail( $user->user_email, $subject, $body, $headers ); } // Вызов при создании уведомления add_action( 'after_insert_user_notification', function( $notif_id ) { $notif = get_notification_by_id( $notif_id ); // ваша функция получения записи notif_send_email( $notif->user_id, $notif->title, $notif->message ); });

Для повышения доставляемости рекомендуется настроить SMTP‑плагин, например, по советам из статьи о PHP 8.4.

5. Оптимизация и кэширование

При большом количестве пользователей запросы к таблице уведомлений могут стать узким местом. Используйте объектный кэш и индексы.

5.1. Кеширование запросов

function notif_get_unread_cached( $user_id, $limit = 20 ) { $cache_key = "notif_unread_{$user_id}_{$limit}"; $cached = wp_cache_get( $cache_key ); if ( false!== $cached ) return $cached; $result = notif_get_unread( $user_id, $limit ); wp_cache_set( $cache_key, $result, '', 300 ); // 5 минут return $result; }

Подробности о MySQL‑кешировании читайте в статье о кэшировании MySQL.

Заключение

Мы создали полноценную систему уведомлений WordPress: надёжную схему БД, REST‑API, интерактивный фронтенд и email‑рассылку. При правильной оптимизации и защите (см. статьи про Drive‑by download и защиту сессий) ваш проект будет масштабироваться без проблем.

❓ Часто задаваемые вопросы

Как хранить уведомления, чтобы они не перегружали wp_posts?

Создайте отдельную таблицу (wp_user_notifications) и используйте $wpdb для CRUD‑операций. Это позволяет добавить индексы по user_id и is_read.

Можно ли получать уведомления без перезагрузки страницы?

Да, используйте REST API и JavaScript‑fetch. Периодический запрос (например, каждые 60 сек.) обновит список in‑app уведомлений.

Как обеспечить доставку email‑уведомлений в почтовые ящики?

Настройте SMTP‑сервер (SMTP‑плагин) и используйте wp_mail с заголовком Content-Type: text/html. Проверьте SPF/DKIM записи домена.

Каким образом кэшировать запросы к базе уведомлений?

Оборачивайте функцию получения уведомлений в wp_cache_get/wp_cache_set. Кешировать можно на 5‑10 минут, после чего сбрасывать при добавлении нового уведомления.