Веб-приложения давно перестали быть просто страницами с формами. Пользователи хотят мгновенных обновлений: чаты, уведомления, совместное редактирование. Обычные HTTP-запросы тут не справляются. На помощь приходят вебсокеты. В этой статье разберём, как подружить Yii2 с вебсокетами, чтобы ваше приложение работало в реальном времени.
Что такое вебсокеты и зачем они нужны в Yii2
Вебсокет — это постоянное двустороннее соединение между браузером и сервером. Представьте телефонный разговор: вы говорите, собеседник отвечает сразу, без задержек. В отличие от HTTP, где клиент каждый раз спрашивает «есть что-нибудь новое?», вебсокет держит канал открытым, и сервер сам присылает данные, когда нужно.
В Yii2 нет встроенного вебсокет-сервера, но это не проблема. Фреймворк отлично расширяется. Мы можем использовать сторонние библиотеки, например, Ratchet или Swoole, и интегрировать их с Yii2-компонентами.
Зачем это в Yii2? Допустим, у вас интернет-магазин. Пользователь оформил заказ — и сразу видит, как статус меняется с «Обрабатывается» на «Отправлен». Или чат поддержки: оператор отвечает, а сообщение появляется без перезагрузки страницы. Всё это — реальное время.
Выбираем инструмент: Ratchet или Swoole
Для PHP есть два популярных решения для вебсокетов: Ratchet и Swoole. Ratchet — это чистый PHP, работает поверх ReactPHP. Swoole — это расширение PHP, написанное на C, даёт высокую производительность, но требует установки.
Сравним их в таблице.
| Характеристика | Ratchet | Swoole |
|---|---|---|
| Установка | Через Composer | Расширение PHP (pecl) |
| Производительность | Средняя | Высокая |
| Сложность освоения | Низкая | Средняя |
| Поддержка Yii2 | Легко интегрировать | Требует адаптации |
Для большинства проектов на Yii2 достаточно Ratchet. Он прост в настройке и не требует экзотики. Swoole выбирайте, если нужна максимальная нагрузка.
Устанавливаем и настраиваем Ratchet в Yii2
Первым делом установим Ratchet через Composer. В корне проекта выполните:
composer require cboden/ratchet
Теперь создадим консольную команду для запуска вебсокет-сервера. В Yii2 это делается через контроллер в папке commands. Создайте файл WebSocketController.php.
<?php
namespace app\commands;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use yii\console\Controller;
use app\components\ChatHandler;
class WebSocketController extends Controller
{
public function actionStart()
{
$server = IoServer::factory(
new HttpServer(
new WsServer(
new ChatHandler()
)
),
8080
);
$this->stdout("Сервер запущен на порту 8080\n");
$server->run();
}
}
Здесь мы создаём сервер на порту 8080 и передаём ему обработчик ChatHandler. Этот класс мы сейчас напишем. Он будет управлять подключениями и сообщениями.
<?php
namespace app\components;
use Ratchet\ConnectionInterface;
use Ratchet\MessageComponentInterface;
class ChatHandler implements MessageComponentInterface
{
protected $clients;
public function __construct()
{
$this->clients = new \SplObjectStorage;
}
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);
}
}
}
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();
}
}
Это простейший чат-сервер: все сообщения от одного клиента рассылаются остальным. Теперь запустим сервер из консоли:
php yii websocket/start
Сервер слушает порт 8080. Осталось подключиться к нему из браузера.
Клиентская часть: JavaScript и WebSocket API
На стороне клиента всё просто. Браузерный WebSocket API входит в стандарт. Подключимся к нашему серверу и отправим сообщение.
const socket = new WebSocket('ws://localhost:8080');
socket.onopen = function() {
console.log('Соединение установлено');
socket.send('Привет, сервер!');
};
socket.onmessage = function(event) {
console.log('Получено: ' + event.data);
};
socket.onclose = function() {
console.log('Соединение закрыто');
};
Этот код можно вставить в <script> на любой странице Yii2. Но чтобы было красиво, добавим простую форму чата.
<div id="chat">
<div id="messages" style="height: 300px; overflow-y: scroll; border: 1px solid #ccc; padding: 10px; margin-bottom: 10px;"></div>
<input type="text" id="messageInput" placeholder="Введите сообщение..." style="width: 80%;">
<button id="sendButton">Отправить</button>
</div>
<script>
const socket = new WebSocket('ws://localhost:8080');
const messages = document.getElementById('messages');
const input = document.getElementById('messageInput');
const button = document.getElementById('sendButton');
socket.onmessage = function(event) {
const div = document.createElement('div');
div.textContent = event.data;
messages.appendChild(div);
messages.scrollTop = messages.scrollHeight;
};
button.onclick = function() {
const text = input.value.trim();
if (text) {
socket.send(text);
input.value = '';
}
};
</script>
Теперь у вас есть рабочий чат. Откройте две вкладки — и увидите, как сообщения летают между ними.
Практические советы и подводные камни
Вот несколько рекомендаций, которые сэкономят вам нервы.
- Не запускайте вебсокет-сервер на том же порту, что и веб-сервер. Используйте отдельный порт, например 8080, и проксируйте через Nginx.
- Обрабатывайте переподключения. Соединение может разорваться. В JavaScript добавьте
socket.oncloseс таймером для повторного подключения. - Используйте WSS для HTTPS. Если сайт работает по HTTPS, вебсокет должен быть WSS (защищённый). Настройте SSL-сертификат.
- Храните состояние в Redis или базе. Если сервер упадёт, история сообщений не потеряется.
Ещё один момент: Ratchet не дружит с Yii2-сессиями из коробки. Если нужно авторизовать пользователя, передавайте токен в URL или первом сообщении, а затем проверяйте его на сервере через компонент Yii.
Что в итоге
Вебсокеты в Yii2 — это не страшно. С помощью Ratchet вы можете добавить реальное время в любое приложение: чаты, уведомления, обновления статусов. Главное — правильно настроить сервер и не забыть про обработку ошибок.
Помните: начинайте с простого, тестируйте каждый шаг. И тогда ваше приложение станет по-настоящему интерактивным.
Студия WNDER



