WebSockets в PHP: создаём real-time приложения без магии

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

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-токены и проверяйте подпись.

Swoole: когда нужна производительность

Блоги

Рекомендаций по книгам