Вы когда-нибудь задумывались, как работают онлайн-чаты, где сообщения приходят мгновенно, без обновления страницы? Вебсокеты — это технология, которая позволяет установить постоянное соединение между браузером и сервером. В этой статье мы разберем, как создать такой чат на Yii2 с использованием вебсокетов. Даже если вы новичок в этой теме, следуя шагам, вы получите работающий чат.
Ссылка на оригинальную статьюЧто такое вебсокеты и зачем они нужны
Вебсокеты — это протокол, который обеспечивает двустороннюю связь между клиентом и сервером. В отличие от обычного HTTP, где клиент отправляет запрос и получает ответ, вебсокеты позволяют серверу отправлять данные клиенту самостоятельно, без запроса. Это идеально для чатов, уведомлений, онлайн-игр и других приложений реального времени.
Представьте, что вы сидите в кафе и общаетесь с другом. Обычный HTTP — это когда вы каждый раз встаете, подходите к стойке и спрашиваете: "Есть ли новые сообщения?" Вебсокеты — это когда официант сам приносит вам кофе, как только он готов. Экономия времени и ресурсов.
Подготовка окружения и установка необходимых компонентов
Для работы нам понадобится Yii2 (базовый или продвинутый шаблон), PHP версии 7.4 или выше, Composer и Node.js (для запуска WebSocket-сервера). Если у вас еще нет Yii2, установите его через Composer:
composer create-project --prefer-dist yiisoft/yii2-app-basic chat
Теперь установим расширение для работы с вебсокетами. Одно из популярных — ratchet/pawl для серверной части и textalk/websocket для клиента. Но мы пойдем более простым путем — используем библиотеку Workerman, которая отлично работает с PHP и не требует Node.js.
composer require workerman/workerman
Workerman — это асинхронный PHP-фреймворк для создания сетевых приложений. Он прост в использовании и поддерживает вебсокеты из коробки.
Создание WebSocket-сервера
Создадим файл server.php в корне проекта. Он будет запускать WebSocket-сервер, который будет принимать сообщения от клиентов и пересылать их всем подключенным пользователям.
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
$ws_worker = new Worker("websocket://0.0.0.0:8080");
$ws_worker->count = 1;
// Массив для хранения всех подключенных клиентов
$clients = [];
$ws_worker->onConnect = function (TcpConnection $connection) use (&$clients) {
$clients[$connection->id] = $connection;
echo "Новый клиент: " . $connection->id . PHP_EOL;
};
$ws_worker->onMessage = function (TcpConnection $connection, $data) use (&$clients) {
$data = json_decode($data, true);
$message = [
'user' => $data['user'],
'text' => $data['text'],
'time' => date('H:i:s')
];
// Отправляем сообщение всем клиентам
foreach ($clients as $client) {
$client->send(json_encode($message));
}
};
$ws_worker->onClose = function (TcpConnection $connection) use (&$clients) {
unset($clients[$connection->id]);
echo "Клиент отключился: " . $connection->id . PHP_EOL;
};
Worker::runAll();
Здесь мы создаем WebSocket-сервер на порту 8080. При подключении нового клиента добавляем его в массив $clients. При получении сообщения от одного клиента отправляем его всем остальным. Просто и эффективно.
Интеграция с Yii2: создание контроллера и представления
Теперь создадим контроллер в Yii2, который будет обрабатывать запросы чата. Создадим ChatController в папке controllers.
<?php
namespace app\controllers;
use Yii;
use yii\web\Controller;
class ChatController extends Controller
{
public function actionIndex()
{
return $this->render('index');
}
}
В представлении views/chat/index.php создадим интерфейс чата. Нам понадобится поле для ввода имени пользователя, поле для ввода сообщения и область для отображения сообщений. Подключим JavaScript для работы с вебсокетами.
<div class="chat-container">
<div class="chat-header">Чат</div>
<div class="chat-messages" id="messages"></div>
<div class="chat-input">
<input type="text" id="user" placeholder="Ваше имя" />
<input type="text" id="message" placeholder="Введите сообщение..." />
<button id="send">Отправить</button>
</div>
</div>
Стилизуем все это в CSS, но для краткости опустим. Добавим JavaScript-код, который будет подключаться к WebSocket-серверу и обрабатывать отправку и получение сообщений.
const ws = new WebSocket('ws://localhost:8080');
const messages = document.getElementById('messages');
const userInput = document.getElementById('user');
const messageInput = document.getElementById('message');
const sendButton = document.getElementById('send');
ws.onopen = function() {
console.log('Соединение установлено');
};
ws.onmessage = function(event) {
const data = JSON.parse(event.data);
const messageElement = document.createElement('div');
messageElement.innerHTML = '<strong>' + data.user + '</strong>: ' + data.text + ' <em>(' + data.time + ')</em>';
messages.appendChild(messageElement);
messages.scrollTop = messages.scrollHeight;
};
sendButton.addEventListener('click', function() {
const user = userInput.value.trim();
const text = messageInput.value.trim();
if (user && text) {
ws.send(JSON.stringify({user: user, text: text}));
messageInput.value = '';
}
});
messageInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
sendButton.click();
}
});
В этом коде мы создаем WebSocket-соединение с адресом ws://localhost:8080. При получении сообщения от сервера добавляем его в блок сообщений. При нажатии на кнопку или Enter отправляем данные на сервер.
Запуск и тестирование
Запустим WebSocket-сервер командой:
php server.php start
Затем запустим встроенный сервер Yii2:
php yii serve
Откройте в браузере http://localhost:8080 (или другой порт, который вы указали) и попробуйте отправить сообщение. Откройте второе окно браузера, чтобы увидеть, как сообщения передаются между клиентами.
netstat -tulpn | grep 8080 для проверки.
Практические советы и лайфхаки
Вот несколько советов, которые пригодятся при разработке чатов на Yii2 с вебсокетами:
- Используйте Redis или базу данных для хранения истории сообщений, чтобы при перезагрузке страницы они не терялись.
- Для продакшена настройте SSL-сертификат, чтобы WebSocket-соединение было защищенным (wss://).
- Ограничьте количество сообщений в чате, чтобы не перегружать сервер.
- Используйте аутентификацию пользователей через Yii2, чтобы знать, кто пишет сообщения.
Сравнение подходов к созданию чатов:
| Подход | Преимущества | Недостатки |
|---|---|---|
| Polling (частые запросы) | Простота реализации | Высокая нагрузка на сервер, задержки |
| Long Polling | Меньше запросов | Сложность, проблемы с масштабированием |
| WebSockets | Реальное время, низкая нагрузка | Требуется специальный сервер |
Заключение
Мы создали простой чат на Yii2 с использованием вебсокетов. Вы узнали, как работает WebSocket-сервер, как интегрировать его с Yii2 и как написать клиентскую часть. Это основа, которую можно расширять: добавлять базу данных, аутентификацию, комнаты, историю сообщений и многое другое.
В итоге вы получили работающий прототип, который можно использовать как фундамент для более сложных приложений. Не бойтесь экспериментировать и улучшать код.
Студия WNDER



