WebSockets в PHP: создаём real-time приложения без магии
Вы когда-нибудь задумывались, почему в современных веб-приложениях уведомления приходят мгновенно, а чаты работают без постоянного нажатия F5? Секрет — в WebSockets. И да, PHP тоже умеет в real-time. В этой статье мы разберёмся, как подружить PHP с WebSockets, напишем живой чат и уведомления, а главное — сделаем это без боли и лишних библиотек.
Если вы привыкли, что PHP — это "запрос-ответ", готовьтесь удивляться. С помощью WebSockets в PHP можно создать полноценные real-time приложения: от простого чата до многопользовательской игры. И всё это — на вашем любимом языке.
Что такое WebSockets и зачем они PHP?
WebSocket — это протокол двусторонней связи между клиентом и сервером. В отличие от обычного HTTP, где клиент постоянно дёргает сервер с вопросом "ну что, есть новости?", WebSocket держит соединение открытым. Сервер сам отправляет данные клиенту, когда они появляются.
Для PHP это настоящий прорыв. Раньше real-time был уделом Node.js или Python с asyncio. Но сейчас real-time приложения на PHP — реальность. Благодаря библиотекам вроде Ratchet и Swoole, PHP может работать как долгоживущий процесс, обрабатывая тысячи одновременных соединений.
Где это пригодится?
- Чаты и мессенджеры;
- Системы уведомлений (новые заказы, сообщения);
- Совместное редактирование документов;
- Онлайн-игры и викторины;
- Мониторинг и дашборды в реальном времени.
Подготовка: что нужно для старта
Для работы с WebSocket сервером на PHP нам понадобится:
- PHP 7.4 или выше (лучше 8.x);
- Composer — менеджер пакетов;
- Библиотека Ratchet (или Swoole для продакшена);
- Базовое понимание ООП и работы с консолью.
Установим Ratchet через Composer:
composer require cboden/ratchet
После установки у вас появится папка vendor и файл composer.json. Всё готово к написанию первого real-time приложения на PHP.
Пишем простой WebSocket сервер на PHP
Создадим файл server.php. Это будет наш WebSocket сервер PHP, который принимает соединения и рассылает сообщения всем подключённым клиентам.
<?php
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
require __DIR__ . '/vendor/autoload.php';
class Chat implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
echo "Сервер запущен!\n";
}
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo "Новое соединение: {$conn->resourceId}\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
foreach ($this->clients as $client) {
if ($from !== $client) {
$client->send($msg);
}
}
echo "Сообщение от {$from->resourceId}: $msg\n";
}
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
echo "Соединение закрыто: {$conn->resourceId}\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "Ошибка: {$e->getMessage()}\n";
$conn->close();
}
}
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();
Запустим сервер из консоли:
php server.php
Всё! Сервер слушает порт 8080 и готов принимать WebSocket-соединения. Теперь напишем клиентскую часть.
Клиент на JavaScript: подключаемся к WebSocket
Создадим простую HTML-страницу index.html:
<!DOCTYPE html>
<html>
<head>
<title>WebSocket чат на PHP</title>
<meta charset="utf-8">
</head>
<body>
<h2>Чат на WebSockets PHP</h2>
<div id="messages"></div>
<input type="text" id="messageInput" placeholder="Введите сообщение...">
<button onclick="sendMessage()">Отправить</button>
<script>
const conn = new WebSocket('ws://localhost:8080');
conn.onopen = function() {
console.log('Подключено к WebSocket серверу PHP');
};
conn.onmessage = function(e) {
const messages = document.getElementById('messages');
const msg = document.createElement('p');
msg.textContent = e.data;
messages.appendChild(msg);
};
conn.onerror = function(error) {
console.error('Ошибка WebSocket:', error);
};
function sendMessage() {
const input = document.getElementById('messageInput');
conn.send(input.value);
input.value = '';
}
</script>
</body>
</html>
Откройте этот файл в браузере, запустите сервер — и вы увидите, как сообщения передаются мгновенно. Это и есть real-time приложение на PHP в действии.
Как улучшить: добавляем комнаты и авторизацию
Базовый чат — это здорово, но в реальных проектах нужны комнаты и авторизация. Давайте расширим наш WebSocket сервер PHP.
Добавим поддержку комнат. Клиент будет отправлять JSON с полями room и message:
<?php
// В классе Chat добавляем массив комнат
protected $rooms = [];
public function onMessage(ConnectionInterface $from, $msg) {
$data = json_decode($msg, true);
if (isset($data['join'])) {
$this->rooms[$data['join']][] = $from;
$from->room = $data['join'];
return;
}
$room = $from->room ?? 'general';
foreach ($this->rooms[$room] as $client) {
if ($from !== $client) {
$client->send($data['message'] ?? $msg);
}
}
}
Теперь клиент может подключаться к разным комнатам, отправляя {"join": "php"} или {"join": "web"}. Сообщения будут видны только участникам комнаты.
Авторизацию можно реализовать через HTTP-заголовки при подключении или через отправку токена первым сообщением. В production используйте JWT-токены и проверяйте подпись.