Вы можете подумать, что создать чат — это сложная задача, однако это проще, чем вы думаете (как и все, что мы публикуем на этом сайте).
Сокеты традиционно были решением, вокруг которого строится большинство систем чата в реальном времени, обеспечивая двунаправленный канал связи между клиентом и сервером. Это означает, что сервер может отправлять сообщения клиентам. Всякий раз, когда вы пишете сообщение чата, идея заключается в том, что сервер получит его и отправит всем остальным подключенным клиентам.
Замечания: как упоминалось в заголовке, эта реализация независима, и мы охватываем только бэкэнд и основные функциональные возможности на стороне клиента. Это зависит от вас, как настроить его с помощью CSS или других вещей.
Требования
- Пакет Ratchet Socketome: Ratchet — это слабосвязанная PHP-библиотека, предоставляющая разработчикам инструменты для создания двунаправленных приложений в реальном времени между клиентами и серверами через WebSockets.
Чтобы включить socketome в ваш проект symfony, используйте composer и выполните следующую команду
composer require cboden/ratchet
Или вы можете изменить свой composer.json
подать потом использовать composer install
,
{
"require": {
"cboden/ratchet": "0.3.*"
}
}
- Браузер это поддерживает сокеты.
И ты готов к работе!
Создание чата
Чтобы начать с простого чата, мы собираемся создать открытую комнату, доступную для всех (при условии, что WebSocket нацелен на указанный URL).
Шаги, чтобы следовать
- Создайте класс Chat.php в
Sockets
папка в вашем комплекте. - Создайте команду Symfony в
Command
папка для запуска чата через командную консоль. - Обработайте сокет с Javascript в представлении.
- Запустите и проверьте свой чат.
Создать сокет
Для начала создайте папку в корневая папка вашего пакета с именем «Sockets» и создайте следующий класс (Chat.php
) в теме.
Этот класс будет обрабатывать все соединения, сообщения и т. Д. Это будет использовано позже при инициализации через консоль (не забудьте изменить пространство имен в соответствии с вашим пакетом).
clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
// Store the new connection to send messages to later
$this->clients->attach($conn);
echo "New connection! ({$conn->resourceId})\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
$numRecv = count($this->clients) - 1;
echo sprintf('Connection %d sending message "%s" to %d other connection%s' . "\n"
, $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');
foreach ($this->clients as $client) {
if ($from !== $client) {
// The sender is not the receiver, send to each client connected
$client->send($msg);
}
}
}
public function onClose(ConnectionInterface $conn) {
// The connection is closed, remove it, as we can no longer send it messages
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
}
Теперь, когда у нас есть обработчик сокетов на стороне сервера, нам нужно создать код для его запуска.
Создать команду для запуска чата
Обычно вы должны сохранить код, чтобы запустить его в php-файле, а затем использовать консоль, используя php file.php
, Однако, как хорошая практика в Symfony, мы собираемся выполнить этот код в команде Symfony, которая облегчит вам задачу, и вы сможете, если вы захотите выполнять команды в контроллерах или других сумасшедших вещах, которые вы хотите выполнить. делать.
Чтобы продолжить, создайте папку в корневая папка вашего пакета с именем «Command» (если он еще не существует) и создайте следующую команду (SocketCommand.php
) на нем .
Не забудьте изменить пространство имен в соответствии с вашим пакетом.
setName('sockets:start-chat')
// the short description shown while running "php bin/console list"
->setHelp("Starts the chat socket demo")
// the full command description shown when running the command with
->setDescription('Starts the chat socket demo')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln([
'Chat socket',// A line
'============',// Another line
'Starting chat, open your browser.',// Empty line
]);
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();
}
}
Теперь все на стороне сервера готово и мы сможем начать наш чат, используя php bin/console sockets:start-chat
в командной строке, однако нам нужно обработать сокет на стороне клиента.
Обрабатывать сокет на стороне клиента, используя Javascript
Для обработки клиентской части вы можете просто добавить следующий код в вашем представлении. Это довольно просто, как вы можете видеть, он открывает Javascript WebSocket, присоединяет самые основные события и отправляет и получает строку JSON с сервера и на сервер, который обрабатывается на стороне клиента. Не стесняйтесь, чтобы сделать это лучше!
Замечания: зависит от вас, где вы хотите разместить код на стороне клиента. Следующий фрагмент может быть использован, т. Е. В любом представлении ветки или в виде простого html-ответа на любом из ваших контроллеров. Не забудьте изменить URL сокета (в этом случае ws://sandbox:8080
в соответствии с вашим тестовым доменом или localhost).
Public chat
// This object will be sent everytime you submit a message in the sendMessage function.
var clientInformation = {
username: new Date().getTime().toString()
// You can add more information in a static object
};
// START SOCKET CONFIG
/**
* Note that you need to change the "sandbox" for the URL of your project.
* According to the configuration in Sockets/Chat.php , change the port if you need to.
* @type WebSocket
*/
var conn = new WebSocket('ws://sandbox:8080');
conn.onopen = function(e) {
console.info("Connection established succesfully");
};
conn.onmessage = function(e) {
var data = JSON.parse(e.data);
Chat.appendMessage(data.username, data.message);
console.log(data);
};
conn.onerror = function(e){
alert("Error: something went wrong with the socket.");
console.error(e);
};
// END SOCKET CONFIG
/// Some code to add the messages to the list element and the message submit.
document.getElementById("form-submit").addEventListener("click",function(){
var msg = document.getElementById("form-message").value;
if(!msg){
alert("Please send something on the chat");
}
Chat.sendMessage(msg);
// Empty text area
document.getElementById("form-message").value = "";
}, false);
// Mini API to send a message with the socket and append a message in a UL element.
var Chat = {
appendMessage: function(username,message){
var from;
if(username == clientInformation.username){
from = "me";
}else{
from = clientInformation.username;
}
// Append List Item
var ul = document.getElementById("chat-list");
var li = document.createElement("li");
li.appendChild(document.createTextNode(from + " : "+ message));
ul.appendChild(li);
},
sendMessage: function(text){
clientInformation.message = text;
// Send info as JSON
conn.send(JSON.stringify(clientInformation));
// Add my own message to the list
this.appendMessage(clientInformation.username, clientInformation.message);
}
};
И ваш общий чат в основном готов к работе.
Запустите чат и протестируйте его
Для запуска чата используйте ранее созданную команду в консоли:
php bin/console sockets:start-chat
Теперь, если вы только что скопировали код на стороне клиента (разметка и JavaScript), протестируйте его Гугл Хром а также Mozilla Firefox (не обязательно те, но 2 разных браузера), перейдите к своему виду в вашем проекте и увидите магию.
Вы сможете увидеть соединения в консоли, с которой вы начали чат:
Поздравляю! Вы только что сделали простой чат, который можно настроить самостоятельно.
Несколько чатов
Предыдущий пример чата ориентирован на корневой путь вашего домена в порту 8080, однако, если ваш чат не предназначен только для одной комнаты, Вы можете создавать разные маршруты сокетов с разными обработчиками.
В этом случае мы будем использовать тот же Chat.php
класс, но обратите внимание, что инициализация отличается, и ваш Команда Symfony должна быть изменена.
В этом случае вместо ws://sandbox:8080
как маршрут сокета, теперь мы изменим его для ws://sandbox:8080/chat
, Теперь наша команда для запуска чата будет:
setName('sockets:start-chat')
// the short description shown while running "php bin/console list"
->setHelp("Starts the chat socket demo")
// the full command description shown when running the command with
->setDescription('Starts the chat socket demo')
;
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$output->writeln([
'Chat socket',// A line
'============',// Another line
'Starting chat, open your browser.',// Empty line
]);
// The domain of your app as first parameter
// Note : if you got problems during the initialization, add as third parameter '0.0.0.0'
// to prevent any error related to localhost :
// $app = new \Ratchet\App('sandbox', 8080,'0.0.0.0');
// Domain as first parameter
$app = new App('sandbox', 8080,'0.0.0.0');
// Add route to chat with the handler as second parameter
$app->route('/chat', new Chat);
// To add another routes, then you can use :
//$app->route('/america-chat', new AmericaChat);
//$app->route('/europe-chat', new EuropeChat);
//$app->route('/africa-chat', new AfricaChat);
//$app->route('/asian-chat', new AsianChat);
// Run !
$app->run();
}
}
Как видите, легко добавить больше маршрутов в порт сокетов, если у вас есть больше классов обработчиков сокетов. Теперь на стороне клиента веб-сокет должен быть теперь:
var conn = new WebSocket('ws://sandbox:8080/chat');
Основное устранение неполадок
Работает локально, но не удаленно или на сервере || Первый пример работает, но несколько маршрутов не
Это функция безопасности! По умолчанию Храповик связывается с 127.0.0.1 который позволяет только соединения от себя. Рекомендуемый подход заключается в том, чтобы поместить Ratchet за прокси, и только тот прокси (локально) будет подключаться.
Если вы хотите открыть Ratchet up (не за прокси-сервером), установите третий параметр App равным 0.0.0.0 (как указано в примере).
Устранение основных неисправностей Ratchet Socketome содержит другие проблемы, которые вы можете найти позже.
Повеселись !