📋 Что получится
- Broadcasting events через Pushler.ru
- Private и Presence каналы
- Авторизация и безопасность
- Асинхронная отправка для высоких нагрузок
Универсальный подход: Примеры на PHP, но API и паттерны работают с любым языком — Node.js, Python, Go, Ruby, Java, C# и др. Pushler.ru предоставляет REST API для интеграции.
⚡ Быстрая настройка
Установка SDK
Bash
# PHP SDK
composer require pushler/php-sdk
# JavaScript SDK (для фронтенда)
npm install @pushler/js
Инициализация на сервере (PHP)
PHP
<?php
// pushler.php — инициализация Pushler
require_once 'vendor/autoload.php';
use PushlerRu\PushlerClient;
// Создаём клиент Pushler
$pushler = new PushlerClient(
'key_ваш_ключ', // Можно вынести в .env или config
'secret_ваш_секрет'
);
// Для проектов с конфигом:
// $pushler = new PushlerClient(
// getenv('PUSHLER_APP_KEY'),
// getenv('PUSHLER_APP_SECRET')
// );
📡 Отправка событий
Базовая отправка события
PHP
<?php
// Подключаем Pushler
require_once 'pushler.php';
// Отправка события в публичный канал
$pushler->trigger(
'news', // Название канала
'article.published', // Название события
[ // Данные
'id' => 123,
'title' => 'Новая статья',
'author' => 'Иван Иванов'
]
);
// Отправка в приватный канал
$pushler->trigger(
'private-user-456',
'notification',
[
'type' => 'info',
'message' => 'У вас новое сообщение'
]
);
// Отправка в несколько каналов сразу
$pushler->trigger(
['private-user-1', 'private-user-2', 'private-user-3'],
'broadcast',
['message' => 'Важное объявление для всех']
);
Пример: Уведомление при создании заказа
PHP
<?php
// create_order.php
require_once 'pushler.php';
// Получаем данные заказа
$orderData = json_decode(file_get_contents('php://input'), true);
$userId = getCurrentUserId();
// Создаём заказ в БД
$pdo = getDbConnection();
$stmt = $pdo->prepare('
INSERT INTO orders (user_id, total, status, created_at)
VALUES (?, ?, "pending", NOW())
');
$stmt->execute([$userId, $orderData['total']]);
$orderId = $pdo->lastInsertId();
// Данные для события
$eventData = [
'order_id' => $orderId,
'status' => 'pending',
'status_text' => 'Ожидает подтверждения',
'total' => $orderData['total'],
'created_at' => date('c')
];
// Уведомляем клиента
$pushler->trigger(
"private-user-{$userId}",
'order.created',
$eventData
);
// Уведомляем менеджеров
$pushler->trigger(
'private-managers',
'order.new',
[
'order_id' => $orderId,
'total' => $orderData['total'],
'customer' => getUserById($userId)
]
);
echo json_encode(['order_id' => $orderId, 'status' => 'created']);
Пример: Обновление статуса заказа
PHP
<?php
// update_order_status.php
require_once 'pushler.php';
$orderId = (int) $_POST['order_id'];
$newStatus = $_POST['status'];
// Обновляем в БД
$pdo = getDbConnection();
$stmt = $pdo->prepare('UPDATE orders SET status = ? WHERE id = ?');
$stmt->execute([$newStatus, $orderId]);
// Получаем данные заказа
$stmt = $pdo->prepare('SELECT * FROM orders WHERE id = ?');
$stmt->execute([$orderId]);
$order = $stmt->fetch(PDO::FETCH_ASSOC);
$statusTexts = [
'pending' => 'Ожидает подтверждения',
'confirmed' => 'Подтверждён',
'processing' => 'Готовится',
'shipped' => 'В доставке',
'delivered' => 'Доставлен'
];
// Отправляем уведомление клиенту
$pushler->trigger(
"private-user-{$order['user_id']}",
'order.status.updated',
[
'order_id' => $orderId,
'status' => $newStatus,
'status_text' => $statusTexts[$newStatus] ?? $newStatus,
'updated_at' => date('c')
]
);
echo json_encode(['success' => true]);
🔐 Авторизация каналов
PHP
<?php
// auth.php — endpoint авторизации каналов
require_once 'pushler.php';
header('Content-Type: application/json');
$channelName = $_POST['channel_name'];
$socketId = $_POST['socket_id'];
$userId = getCurrentUserId();
// Проверяем авторизацию
if (!$userId) {
http_response_code(401);
echo json_encode(['error' => 'Unauthorized']);
exit;
}
// Проверяем доступ к каналу
if (!canAccessChannel($userId, $channelName)) {
http_response_code(403);
echo json_encode(['error' => 'Forbidden']);
exit;
}
// Для presence-каналов
if (str_starts_with($channelName, 'presence-')) {
$user = getUserById($userId);
$auth = $pushler->authorizePresenceChannel($channelName, $socketId, [
'user_id' => (string) $userId,
'user_info' => [
'name' => $user['name'],
'avatar' => $user['avatar']
]
]);
echo json_encode($auth);
exit;
}
// Для приватных каналов
$auth = $pushler->authorizeChannel($channelName, $socketId);
echo json_encode($auth);
// ============================================
// Функция проверки доступа
// ============================================
function canAccessChannel(int $userId, string $channelName): bool
{
// Приватный канал пользователя
if (preg_match('/^private-user-(\d+)$/', $channelName, $matches)) {
return (int) $matches[1] === $userId;
}
// Канал заказа — владелец или админ
if (preg_match('/^private-order-(\d+)$/', $channelName, $matches)) {
$orderId = (int) $matches[1];
$order = getOrderById($orderId);
return $order && ($order['user_id'] === $userId || isAdmin($userId));
}
// Канал менеджеров
if ($channelName === 'private-managers') {
return isManager($userId);
}
// Presence-канал чата
if (preg_match('/^presence-chat-(\d+)$/', $channelName, $matches)) {
$chatId = (int) $matches[1];
return userHasAccessToChat($userId, $chatId);
}
return false;
}
🌐 Клиент (JavaScript)
Подключение и подписка
HTML
<!-- Подключение SDK -->
<script src="https://cdn.pushler.ru/sdk/pushler.min.js"></script>
JavaScript
// Инициализация
const pushler = new PushlerClient({
appKey: 'key_ваш_ключ',
authEndpoint: '/auth.php'
});
pushler.on('connected', () => {
console.log('Подключено к Pushler');
// Публичный канал — не требует авторизации
const newsChannel = pushler.subscribe('news');
newsChannel.on('article.published', (data) => {
console.log('Новая статья:', data.title);
});
// Приватный канал пользователя
const userChannel = pushler.subscribe(`private-user-${userId}`);
userChannel.on('notification', (data) => {
showNotification(data.message);
});
userChannel.on('order.status.updated', (data) => {
updateOrderStatus(data.order_id, data.status, data.status_text);
});
// Presence-канал (для онлайн-статуса)
const chatChannel = pushler.subscribe(`presence-chat-${chatId}`);
chatChannel.on('pushler:subscription_succeeded', (data) => {
console.log('Онлайн:', Object.values(data.members).map(m => m.name));
});
chatChannel.on('pushler:member_added', (member) => {
console.log(`${member.info.name} присоединился`);
});
chatChannel.on('pushler:member_removed', (member) => {
console.log(`${member.info.name} вышел`);
});
});
// Обработка ошибок
pushler.on('error', (error) => {
console.error('Ошибка Pushler:', error.message);
});
Vue 3 компонент для отслеживания заказа
Vue
<!-- OrderTracker.vue -->
<template>
<div class="order-tracker">
<div class="status" :class="order.status">
{{ statusText }}
</div>
<div class="timeline">
<div
v-for="step in steps"
:key="step.status"
:class="['step', { active: isStepActive(step.status), done: isStepDone(step.status) }]"
>
<div class="dot"></div>
<div class="label">{{ step.label }}</div>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue';
import PushlerClient from '@pushler/js';
const props = defineProps({
orderId: { type: Number, required: true },
userId: { type: Number, required: true },
initialStatus: { type: String, required: true },
appKey: { type: String, required: true }
});
const order = ref({ status: props.initialStatus });
const steps = [
{ status: 'pending', label: 'Ожидание' },
{ status: 'confirmed', label: 'Подтверждён' },
{ status: 'processing', label: 'Готовится' },
{ status: 'shipped', label: 'Доставка' },
{ status: 'delivered', label: 'Доставлен' }
];
const statusTexts = {
pending: 'Ожидает подтверждения',
confirmed: 'Заказ подтверждён',
processing: 'Готовим ваш заказ',
shipped: 'Заказ в пути',
delivered: 'Доставлен'
};
const statusText = computed(() => statusTexts[order.value.status] || order.value.status);
const statusOrder = ['pending', 'confirmed', 'processing', 'shipped', 'delivered'];
const isStepActive = (status) => status === order.value.status;
const isStepDone = (status) => statusOrder.indexOf(status) < statusOrder.indexOf(order.value.status);
let pushler = null;
let channel = null;
onMounted(() => {
pushler = new PushlerClient({
appKey: props.appKey,
authEndpoint: '/auth.php'
});
pushler.on('connected', () => {
channel = pushler.subscribe(`private-user-${props.userId}`);
channel.on('order.status.updated', (data) => {
if (data.order_id === props.orderId) {
order.value.status = data.status;
showToast(`Статус заказа: ${data.status_text}`);
}
});
});
});
onUnmounted(() => {
channel?.unsubscribe();
pushler?.disconnect();
});
</script>
🔄 Асинхронная отправка
Для высоконагруженных проектов рекомендуем использовать очереди:
PHP
<?php
// Добавляем задачу в очередь (Redis/RabbitMQ/DB)
function queuePushlerEvent(string $channel, string $event, array $data): void
{
$job = [
'channel' => $channel,
'event' => $event,
'data' => $data,
'created_at' => time()
];
// Пример с Redis
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->rPush('pushler_queue', json_encode($job));
}
// Worker для обработки очереди
// worker.php — запускается отдельным процессом
require_once 'pushler.php';
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
while (true) {
$jobJson = $redis->blPop('pushler_queue', 5);
if ($jobJson) {
$job = json_decode($jobJson[1], true);
try {
$pushler->trigger($job['channel'], $job['event'], $job['data']);
echo "Отправлено: {$job['event']} в {$job['channel']}\n";
} catch (Exception $e) {
echo "Ошибка: {$e->getMessage()}\n";
// Можно добавить повторную попытку
}
}
}
📊 Примеры событий
Уведомление пользователю
PHP
<?php
// Функция отправки уведомления
function sendNotification(int $userId, string $type, string $title, string $message): void
{
global $pushler;
$pushler->trigger(
"private-user-{$userId}",
'notification.received',
[
'id' => uniqid('notif_'),
'type' => $type, // 'info', 'success', 'warning', 'error'
'title' => $title,
'message' => $message,
'created_at' => date('c')
]
);
}
// Использование
sendNotification(123, 'success', 'Заказ оплачен! 🎉', 'Ваш заказ #456 успешно оплачен.');
sendNotification(123, 'info', 'Новое сообщение', 'Вам написал менеджер.');
Новое сообщение в чате
PHP
<?php
// При отправке сообщения в чат
function broadcastChatMessage(int $chatId, array $message, ?string $excludeSocketId = null): void
{
global $pushler;
$pushler->trigger(
"presence-chat-{$chatId}",
'message.sent',
[
'message' => [
'id' => $message['id'],
'content' => $message['content'],
'user' => [
'id' => $message['user_id'],
'name' => $message['user_name'],
'avatar' => $message['user_avatar']
],
'created_at' => $message['created_at']
]
],
$excludeSocketId // Исключаем отправителя
);
}
⚠️ Типичные ошибки
1. Событие не отправляется
PHP
// ❌ Неправильно — неверные ключи
$pushler = new PushlerClient('wrong_key', 'wrong_secret');
// ✅ Правильно — проверьте ключи в личном кабинете
$pushler = new PushlerClient(
'key_xxxxxxxxxxxxxxxx', // Ваш App Key
'secret_xxxxxxxxxxxxxxxx' // Ваш App Secret
);
2. Ошибка авторизации канала
PHP
// ❌ Неправильно — auth.php возвращает HTML вместо JSON
echo "<html>Error</html>";
// ✅ Правильно — всегда JSON
header('Content-Type: application/json');
http_response_code(403);
echo json_encode(['error' => 'Forbidden']);
3. Не указан authEndpoint на клиенте
JavaScript
// ❌ Неправильно — нет authEndpoint для приватных каналов
const pushler = new PushlerClient({ appKey: 'key_xxx' });
pushler.subscribe('private-user-123'); // Ошибка!
// ✅ Правильно
const pushler = new PushlerClient({
appKey: 'key_xxx',
authEndpoint: '/auth.php' // Путь к вашему скрипту авторизации
});
4. CORS ошибки
PHP
// auth.php — добавьте CORS заголовки если фронт на другом домене
header('Access-Control-Allow-Origin: https://your-frontend.com');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Headers: Content-Type');
header('Access-Control-Allow-Credentials: true');
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
exit(0);
}
Готовы попробовать?
Создайте бесплатный аккаунт и начните интеграцию за пару минут