Как написать чат для сайта

#Руководства

  • 22 апр 2019

  • 13

Когда обычных комментариев становится недостаточно, приходит время создать чат.

 vlada_maestro / shutterstock

Евгений Кучерявый

Пишет о программировании, в свободное время создаёт игры. Мечтает открыть свою студию и выпускать ламповые RPG.

С помощью чата пользователи общаются друг с другом, повышая интерес к сайту. Это важный элемент для вебинарных площадок, порталов со службой поддержки и страниц, где необходимо более живое, нефорумное общение. Гайд поможет на практике скомбинировать знания по HTML, JS, PHP и AJAX и создать готовый продукт.

Удобство для пользователей превыше всего. Позаботьтесь, чтобы чат соответствовал современным требованиям:

  • сообщения отображаются корректно на всех устройствах;
  • их загрузка и отправка происходят без обновления страницы;
  • есть дополнительный контент — изображения, аудиосообщения, смайлики, стикеры и прочее.

В первую очередь создаём форму отправки и контейнер для отображения сообщений:

<div class='chat'>
	<div class='chat-messages'>
		<div class='chat-messages__content' id='messages'>
			Загрузка...
		</div>
	</div>
	<div class='chat-input'>
		<form method='post' id='chat-form'>
			<input type='text' id='message-text' class='chat-form__input' placeholder='Введите сообщение'> <input type='submit' class='chat-form__submit' value='=>'>
		</form>
	</div>
</div>

.chat {
	border:1px solid #333;
	margin:15px;
	width:40%;
	height:70%;
	background:#555;
	color:#fff;
}

.chat-messages {
	min-height:93%;
	max-height:93%;
	overflow:auto;
}

.chat-messages__content {
	padding:1px;
}

.chat__message {
	border-left:3px solid #333;
	margin-top:2px;
	padding:2px;
}

.chat__message_black {
	border-color:#000;
}

.chat__message_blue {
	border-color:blue;
}

.chat__message_green {
	border-color:green;
}

.chat__message_red {
	border-color:red;
}

.chat-input {
	min-height:6%;
}
input {
	font-family:arial;
	font-size:16px;
	vertical-align:middle;
	background:#333;
	color:#fff;
	border:0;
	display:inline-block;
	margin:1px;
	height:30px;
}

.chat-form__input {
	width:79%;
}

.chat-form__submit {
	width:18%;
}

Первый этап пройден:

В первую очередь уделим внимание главным функциям чата, а после доработаем внешний вид.

Сообщения будут отправляться и загружаться с помощью AJAX. На JavaScript пишем функции работы с интерфейсом и связи с серверной частью, а на PHP — методы обработки полученных данных и взаимодействия с базой данных.

var messages__container = document.getElementById('messages'); 
//Контейнер сообщений — скрипт будет добавлять в него сообщения

var interval = null; //Переменная с интервалом подгрузки сообщений

var sendForm = document.getElementById('chat-form'); //Форма отправки
var messageInput = document.getElementById('message-text'); //Инпут для текста сообщения

Она получает переменную act, в которой хранится одно из трёх значений: auth (авторизация), load (загрузка) и send (отправка). От них зависит, какая информация будет передана в PHP-файл.

function send_request(act, login = null, password = null) {//Основная функция
	//Переменные, которые будут отправляться
	var var1 = null;
	var var2 = null;
	
	if(act == 'auth') {
		//Если нужно авторизоваться, получаем логин и пароль, которые были переданы в функцию
		var1 = login;
		var2 = password;
	} else if(act == 'send') {
//Если нужно отправить сообщение, то получаем текст из поля ввода
		var1 = messageInput.value;
	}
	
	$.post('includes/chat.php',{ //Отправляем переменные
		act: act,
		var1: var1,
		var2: var2
	}).done(function (data) { 
		//Заносим в контейнер ответ от сервера
		messages__container.innerHTML = data;
		if(act == 'send') {
			//Если нужно было отправить сообщение, очищаем поле ввода
			messageInput.value = '';
		}
	});
}

И укажем для нашей функции интервал выполнения:

function update() {
	send_request('load');
}
interval = setInterval(update,500);

После отлавливается событие отправки формы — это поможет отказаться от обновления страницы:

sendForm.onsubmit = function () {
	send_request('send');
	return false; //Возвращаем ложь, чтобы остановить классическую отправку формы
};

Теперь займёмся самим обработчиком. В первую очередь с помощью функции session_start () запускается сессия, затем подключается база данных:

session_start();//Подключение должно быть на первой строчке в коде, иначе появится ошибка
$db = mysqli_connect("localhost","login","password"); 
mysqli_select_db($db,"chat");
//Заносим данные админа в сессию
$_SESSION['login'] = 'admin';
$_SESSION['password'] = 'admin';
$_SESSION['id'] = 1;

function auth($db,$login,$pass) {
	//Находим совпадение в базе данных
	$result = mysqli_query($db,"SELECT * FROM userlist WHERE login='$login' AND password='$pass'");
	if($result) {
		if(mysqli_num_rows($result) == 1) {//Проверяем, одно ли совпадение
			$user = mysqli_fetch_array($result); //Получаем данные пользователя и заносим их в сессию
			$_SESSION['login'] = $login;
			$_SESSION['password'] = $pass;
			$_SESSION['id'] = $user['id'];
			return true; //Возвращаем true, потому что авторизация успешна
		} else {
			unset($_SESSION); //Удаляем все данные из сессии и возвращаем false, если совпадений нет или их больше 1
			return false;
		}
	} else {
		return false; //Возвращаем ложь, если произошла ошибка
	}
}

function load($db) {
	$echo = "";
	if(auth($db,$_SESSION['login'],$_SESSION['password'])) {//Проверяем успешность авторизации
		$result = mysqli_query($db,"SELECT * FROM messages"); //Запрашиваем сообщения из базы
		if($result) {
			if(mysqli_num_rows($result) >= 1) {
				while($array = mysqli_fetch_array($result)) {//Выводим их с помощью цикла
					$user_result = mysqli_query($db,"SELECT * FROM userlist WHERE id='$array[user_id]'");//Получаем данные об авторе сообщения
					if(mysqli_num_rows($user_result) == 1) {
						$user = mysqli_fetch_array($user_result);
						$echo .= "<div class='chat__message chat__message_$user[nick_color]'><b>$user[login]:</b> $array[message]</div>"; //Добавляем сообщения в переменную $echo
					}
				}
			
			} else {
				$echo = "Нет сообщений!";//В базе ноль записей
			}
		}
	} else {
		$echo = "Проблема авторизации";//Авторизация не удалась
	}
	
	return $echo;//Возвращаем результат работы функции
}

function send($db,$message) {
	if(auth($db,$_SESSION['login'],$_SESSION['password'])) {//Если авторизация удачна
		$message = htmlspecialchars($message);//Заменяем символы ‘<’ и ‘>’на ASCII-код
		$message = trim($message); //Удаляем лишние пробелы
		$message = addslashes($message); //Экранируем запрещенные символы
		$result = mysqli_query($db,"INSERT INTO messages (user_id,message) VALUES ('$_SESSION[id]','$message')");//Заносим сообщение в базу данных
	}
	return load($db); //Вызываем функцию загрузки сообщений
}

В функции уже присутствует несложная валидация, но можно добавить и другие меры защиты от инъекций и спама:

  • проверку на дублирование прошлого сообщения;
  • удаление внешних ссылок;
  • цензуру мата;
  • премодерацию сообщений у некоторых групп пользователей и так далее.

Теперь, когда все функции готовы, пропишем их вызов.

//Получаем переменные из супермассива $_POST
//Тут же их можно проверить на наличие инъекций
if(isset($_POST['act'])) {$act = $_POST['act'];}
if(isset($_POST['var1'])) {$var1 = $_POST['var1'];}
if(isset($_POST['var2'])) {$var2 = $_POST['var2'];}

switch($_POST['act']) {//В зависимости от значения act вызываем разные функции
	case 'load': 
		$echo = load($db); //Загружаем сообщения
	break;
	
	case 'send': 
		if(isset($var1)) {
			$echo = send($db,$var1); //Отправляем сообщение
		}
	break;
	
	case 'auth': 
		if(isset($var1) && isset($var2)) {//Авторизуемся
			if(auth($db,$var1,$var2)) {
				$echo = load($db);
			}
		}
	break;
}

echo $echo;//Выводим результат работы кода

Со стороны фронтенда мы ещё не реализовали авторизацию, но уже можем проверить чат, потому что в самом начале данные администратора были занесены в сессию. Вот как это выглядит:

Теперь, когда чат работает, пора добавить авторизацию. Для этого можно создать отдельную форму во фронте, но можно обойтись и модальными окнами. В функции send_request () дополним отправку запроса:

$.post('includes/chat.php',{
	act: act,
	var1: var1,
	var2: var2
}).done(function (data) {
	messages__container.innerHTML = data;
	if(data == 'Проблема авторизации') {
		clearInterval(interval); //Если проблема авторизации, отключаем автообновление
		if(login == null && password == null) {
			login = prompt('Введите логин: ');//Запрашиваем логин
			if(login != null) {
				password = prompt('Введите пароль: ');//Запрашиваем пароль
				send_request('auth',login,password); //Отправляем еще один запрос
			}
		}
	} 
	if(act == 'auth') {
		interval = setInterval(update,500); //Заново запускаем автообновление
	}
	if(act == 'send') {
		messageInput.value = '';
	}
});

Вот как это выглядит:

Минимальные возможности чата у нас есть, и продукт можно запускать в релиз, но добавим ещё несколько полезных штук.

Создадим свой набор смайликов чата. Работать это будет так:

  • пользователь открывает специальное окошко и кликает по смайлику;
  • в поле ввода добавляется код смайлика (например, : sad: или: crazy:);
  • при выводе сообщения код смайлика заменяется на изображение.

Для начала добавим контейнер со смайликами и кнопку для его открытия:

<form method='post' id='chat-form'>
<div class='emojis-container emojis-container_hidden' id='emojis'></div>
	<img src='/images/emojis/happy.png' class='emoji-img' id='emoji-button'>
<input type='text' id='message-text' class='chat-form__input' placeholder='Введите сообщение'> 
<input type='submit' class='chat-form__submit' value='=>'>
</form>

Зададим стили:

.emojis-container {
	position:absolute;
	z-index:100;
	background:#555;
	border:1px solid #333;
	padding:2px;
	max-width:38%;
	top:20px;
}

.emojis-container_hidden {
	left:-9999999999999999px;
}

.emoji-img {
	vertical-align:middle;
	width:20px;
	margin:1px;
	cursor:pointer;
}

Добавим скрипт для загрузки смайликов и открытия меню с ними:

//Создаем переменные
var emojis__container = document.getElementById('emojis');
var emojis__button = document.getElementById('emoji-button');
var showed = false;

function getEmojis() {//Получаем смайлики из PHP-файла
	$.post('/includes/chat.php',{act: 'load-emojis'}).done(function (data) {
		emojis__container.innerHTML = data;
	});
}

function showEmojis() {//Добавляем отображение и скрытие окна
	if(showed) {
		emojis__container.setAttribute('class','emojis-container emojis-container_hidden');
		showed = false;
	} else {
		emojis__container.setAttribute('class','emojis-container');
		showed = true;
	}
}

А теперь и функцию добавления смайлика в поле:

function addEmoji(title) {
	messageInput.value += " " + title + " ";
//Тут же можно добавить закрытие контейнера
messageInput.focus();
}

После этого укажем, когда вызываются функции:

$(document).ready(function (){
	$(".emoji-add").on("click", function () {addEmoji($(this).attr('title'));});//Добавление
});
emojis__button.addEventListener('click',showEmojis); 

getEmojis(); //Сразу же вызываем получение смайликов

Приступим к загрузке смайликов и их преобразованию на PHP:

function getEmojis() {
	$dir = '../images/emojis';
	$echo = "";
	$files = scandir($dir);
	
	for($i = 0; $i != count($files); $i++) {
		$ext = explode('.',$files[$i]);
		if($ext[1] == 'png') {
			$echo .= "<img src='/images/emojis/".$files[$i]."' title=':"</span>.$ext[<span class="hljs-number" style="color: #ff73fd;">0</span>].<span class="hljs-string" style="color: #a8ff60;">":' class='emoji-img emoji-add'> ";
		} 
	}
	return $echo;
}

Эта функция сканирует папку со смайликами, а потом проверяет расширение файлов. Она очень удобна, потому что отображает в формате PNG все смайлики, которые мы добавили.

Чтобы вызвать её, добавим ещё один case в функцию switch () в конце обработчика:

case 'load-emojis': 
	$echo = getEmojis();
break;

Теперь с помощью регулярных выражений можно заменять код смайлика на изображение:

function transformEmoji($message) {
	$pattern = '/(:S*:)/i'; //Паттерн смайлика
	if(preg_match($pattern,$message,$matches)) {//Ищем все совпадения для смайлика одного типа — только :happy: или только :sad:
		$path = explode(":",$matches[0]);
		if(file_exists("../images/emojis/".$path[1].".png")) {//Проверяем, существует ли такое изображение
			$message = preg_replace("/".$matches[0]."/","<img src='/images/emojis/$path[1].png' class='emoji-img'>",$message);//Заменяем код на изображение
		}
		$message = transformEmoji($message); //Повторяем, пока в $message есть коды смайликов
	}
	return $message;
}

Вызывается эта функция при загрузке сообщений:

$array['message'] = transformEmoji($array['message']);

Вот как это выглядит:

Чтобы добавить возможность отвечать кому-то конкретному, изменим функцию addEmoji (). При нажатии на ник собеседника будет меняться текст в поле ввода.

Для этого в load () изменим формат сообщений, добавив span к нику:

$echo .= "<div class='chat__message chat__message_$user[nick_color]'><b><span class='answer-span'>$user[login]</span>:</b> $array[message]</div>";

Пишем саму функцию:

function addAnswer(login) {
	messageInput.value = login + ", " + messageInput.value;
	messageInput.focus();
}

И вызываем функцию:

$(document).ready(function (){
	$(".add-answer").on("click", function () {addEmoji($(this).text());});
});

Одной статьи недостаточно, чтобы охватить все возможности PHP и JS для разработки чатов. С помощью этих языков легко добавить:

  • ответ на конкретные сообщения;
  • форматирование текста;
  • отправку аудио;
  • разные «комнаты»;
  • чат-бота и многое другое.

Учись бесплатно:
вебинары по программированию, маркетингу и дизайну.

Участвовать

Научитесь: Веб-разработчик с нуля до PRO
Узнать больше

Одним из самых простых и доступных способов повысить интерес к чату считается создание чата. Он выступает удобным каналом общения с посетителями, причем при должном внимании к разработке и последующим коммуникациям позволяет заметно увеличить трафик интернет-ресурса. Особенно интересным такое решение становится для онлайн-торговли, так как при минимуме трудозатрат способно обеспечить резкий рост продаж и, как следствие, прибыли. Рассмотрим подробнее, что необходимо для быстрого и беспроблемного создания чата.

Стандартные требования к чату для сайта

Этап №1. Программирование каркаса чата с помощью HTML

Этап №2. Программирование основной части чата посредством JS и PHP

Быстрое создание чата – обзор готовых решений

Что почитать и посмотреть по теме?

Стандартные требования к чату для сайта

Эффективное функционирование чата предполагает обязательное выполнение нескольких условий. Ключевыми из них выступают такие:

  1. Корректное отображение сообщений на любых видах устройств – от персонального компьютера до смартфона.
  2. Быстрая и четкая загрузка переписки без необходимости каждый раз обновлять страницу.
  3. Интеграция с социальными сетями и/или популярными мессенджерами.
  4. Доступность для пользователей дополнительных опций, способных разнообразить общение и сделать его более интересным, например, смайлики, стикеры, изображения или возможность записать аудио.

Этап №1. Программирование каркаса чата с помощью HTML

Сначала требуется создать основные элементы будущего чата. Их два: форма отправки и так называемый контейнер, необходимый для отображения переписки, состоящей из отдельных сообщений. Исходный код программы пишется на HTML и имеет следующий вид.

<div class='chat'>

<div class='chat-messages'>

<div class='chat-messages__content' id='messages'>

Загрузка...

</div>

</div>

<div class='chat-input'>

<form method='post' id='chat-form'>

<input type='text' id='message-text' class='chat-form__input' placeholder='Введите сообщение'> <input type='submit' class='chat-form__submit' value='=>'>

</form>

</div>

</div>

Далее на том же языке программирования задаются стили будущего чата. Исходный код имеет примерно следующий вид.

.chat {

border:1px solid #333;

margin:15px;

width:40%;

height:70%;

background:#555;

color:#fff;

}

.chat-messages {

min-height:93%;

max-height:93%;

overflow:auto;

}

.chat-messages__content {

padding:1px;

}

.chat__message {

border-left:3px solid #333;

margin-top:2px;

padding:2px;

}

.chat__message_black {

border-color:#000;

}

.chat__message_blue {

border-color:blue;

}

.chat__message_green {

border-color:green;

}

.chat__message_red {

border-color:red;

}

.chat-input {

min-height:6%;

}

input {

font-family:arial;

font-size:16px;

vertical-align:middle;

background:#333;

color:#fff;

border:0;

display:inline-block;

margin:1px;

height:30px;

}

.chat-form__input {

width:79%;

}

.chat-form__submit {

width:18%;

}

Этап №2. Программирование основной части чата посредством JS и PHP

На втором и главном этапе создания чата формируется его функционал. Необходимые для этого действия разбиваются на несколько отдельных стадий – по количеству функций. Для отправки и загрузки сообщений целесообразно задействовать AJAX. Основной функционал интерфейса и обмен данными с сервером программируется на JavaScript. Взаимодействие с базами данных и методы обработки последних пишутся на языке PHP.

Переменные на JavaScript

Создание переменных происходит по стандартной схеме. Исходный код выглядит следующим образом. Для большей наглядности приводятся поясняющие комментарии к каждому типу переменных.

var messages__container = document.getElementById('messages'); 

//Контейнер сообщений — скрипт будет добавлять в него сообщения

var interval = null; //Переменная с интервалом подгрузки сообщений

var sendForm = document.getElementById('chat-form'); //Форма отправки

var messageInput = document.getElementById('message-text'); //Инпут для текста сообщения

Запросы

Назначение функции запросов – получение переменной act, которая используется для хранения одного из трех возможных значений:

  • авторизация (auth);
  • загрузка (load);
  • отправка (send).

Далее указанное программой значение направляется в PHP-файл. Исходный код функции занимает больше места и выглядит так.

function send_request(act, login = null, password = null) {//Основная функция

//Переменные, которые будут отправляться

var var1 = null;

var var2 = null;

if(act == 'auth') {

//Если нужно авторизоваться, получаем логин и пароль, которые были переданы в функцию

var1 = login;

var2 = password;

} else if(act == 'send') {

//Если нужно отправить сообщение, то получаем текст из поля ввода

var1 = messageInput.value;

}

$.post('includes/chat.php',{ //Отправляем переменные

act: act,

var1: var1,

var2: var2

}).done(function (data) { 

//Заносим в контейнер ответ от сервера

messages__container.innerHTML = data;

if(act == 'send') {

//Если нужно было отправить сообщение, очищаем поле ввода

messageInput.value = '';

}

});

}

Обновление

Как было отмечено выше, обновление чата должно происходить автоматически, то есть без участия пользователя. Решение задачи достигается за счет написания кода, состоящего из трех частей: задание интервала выполнения функции обновления, отлавливание отправки формы и создание обработчика информации. Итоговый результат выглядит так.

function update() {

send_request('load');

}

interval = setInterval(update,500);

sendForm.onsubmit = function () {

send_request('send');

return false; //Возвращаем ложь, чтобы остановить классическую отправку формы

};

session_start();//Подключение должно быть на первой строчке в коде, иначе появится ошибка

$db = mysqli_connect("localhost","login","password"); 

mysqli_select_db($db,"chat");

//Заносим данные админа в сессию

$_SESSION['login'] = 'admin';

$_SESSION['password'] = 'admin';

$_SESSION['id'] = 1;

Авторизация

Назначение функции – идентификация конкретного пользователя. Она обеспечивается по обычной схеме.

function auth($db,$login,$pass) {

//Находим совпадение в базе данных

$result = mysqli_query($db,"SELECT * FROM userlist WHERE login='$login' AND password='$pass'");

if($result) {

if(mysqli_num_rows($result) == 1) {//Проверяем, одно ли совпадение

$user = mysqli_fetch_array($result); //Получаем данные пользователя и заносим их в сессию

$_SESSION['login'] = $login;

$_SESSION['password'] = $pass;

$_SESSION['id'] = $user['id'];

return true; //Возвращаем true, потому что авторизация успешна

} else {

unset($_SESSION); //Удаляем все данные из сессии и возвращаем false, если совпадений нет или их больше 1

return false;

}

} else {

return false; //Возвращаем ложь, если произошла ошибка

}

}

Загрузка

Функция загрузки позволяет разместить сообщение в чате переписки. Она имеет достаточно объемный вид, так как является одной из самых сложных.

function load($db) {

$echo = "";

if(auth($db,$_SESSION['login'],$_SESSION['password'])) {//Проверяем успешность авторизации

$result = mysqli_query($db,"SELECT * FROM messages"); //Запрашиваем сообщения из базы

if($result) {

if(mysqli_num_rows($result) >= 1) {

while($array = mysqli_fetch_array($result)) {//Выводим их с помощью цикла

$user_result = mysqli_query($db,"SELECT * FROM userlist WHERE id='$array[user_id]'");//Получаем данные об авторе сообщения

if(mysqli_num_rows($user_result) == 1) {

$user = mysqli_fetch_array($user_result);

$echo .= "<div class='chat__message chat__message_$user[nick_color]'><b>$user[login]:</b> $array[message]</div>"; //Добавляем сообщения в переменную $echo

}

}

} else {

$echo = "Нет сообщений!";//В базе ноль записей

}

}

} else {

$echo = "Проблема авторизации";//Авторизация не удалась

}

return $echo;//Возвращаем результат работы функции

}

Отправка сообщений

Еще одна непростая для написания исходного кода функция. В самом лаконичном виде она создается следующим образом.

function send($db,$message) {

if(auth($db,$_SESSION['login'],$_SESSION['password'])) {//Если авторизация удачна

$message = htmlspecialchars($message);//Заменяем символы ‘<’ и ‘>’на ASCII-код

$message = trim($message); //Удаляем лишние пробелы

$message = addslashes($message); //Экранируем запрещенные символы

$result = mysqli_query($db,"INSERT INTO messages (user_id,message) VALUES ('$_SESSION[id]','$message')");//Заносим сообщение в базу данных

}

return load($db); //Вызываем функцию загрузки сообщений

}

Данный формат функции обладает минимальными возможностями отправки сообщений.

При желании пользователя могут быть добавлены дополнительные опции. Например, автоматическое удаление мата или цензура на использование внешних ссылок. Но это ведет к усложнению программного кода.

Вызов функций

На завершающем этапе разработки чата остается объединить созданные функции в единую программу. Сделать это несложно, главное – соблюдать последовательность действий, а после дописания кода провести тестирование приложения.

Дополнительный функционал

Выполнение перечисленных выше действий позволяет получить на выходе вполне работоспособный чат. При желании разработчика в него могут быть добавлены дополнительные функции. Например, возможность поставить смайлик, которая реализуется посредством выполнения трех действий:

  • открытием специального кона и выбором из списка доступных нужного изображения;
  • добавлением кода смайлика в поле ввода сообщения;
  • заменой кода на изображение при выводе сообщения на экране получателя.

Еще одной полезной функцией выступает опция ответа на конкретное сообщение определенного пользователя. Как и в случае смайлика, ее добавление требует написания дополнительного кода, хоть и не очень сложного.

Быстрое создание чата – обзор готовых решений

Для получения работающего онлайн-чата совсем не обязательно заниматься программированием самостоятельно. Одним из возможных путей решения задачи выступает использование готового решения, предлагаемого специализированными компаниями. К числу наиболее популярных сервисов онлайн-чатов, доступных на отечественном рынке, можно отнести такие:

  1. Carrot quest. Обладает обширным функционалом, включающим: интеграцию с социальными сетями и мессенджерами, а также WordPress, детальную статистику, опцию сохранения переписки, версию для мобильных устройств и т.д.

  2. LiveTex. Простой и удобный готовый онлайн-чат, который приспосабливается под нужды пользователя посредством множества настроек. Имеют мобильную версию, быстро и без проблем интегрируется с социальными сетями, обладает функцией приема платежей.
  3. МультиЧат. Многофункциональный чат со стандартным набором возможностей – от обратного звонка доя автоматического сбора статистики. Бонусом становится специально разработанная форма заявки, которая используется для оформления заказа.
  4. JivoSite. Лаконичный по оформлению и требуемым ресурсам онлайн-чат. Обладает обычным для подобных сервисов функционалом. В качестве дополнительной предоставляется опция для сбора лидов.

Что почитать и посмотреть по теме?

  1. Учебник HTML для начинающих.
  2. Руководство пользователя JavaScript.
  3. Руководство пользователя по PHP.
  4. М. В. Акулич «Чат-боты и маркетинг».
  5. Срини Джанарсанам «Разработка чат-ботов и разговорных интерфейсов».
  6. Видео ролик на YouTube «Создадим онлайн-чат на PHP и JavaScript».
  7. Видео ролик на YouTube «Создание чата».
  8. Видео ролик на YouTube «Простой чат на PHP. Часть 1».

FAQ

Для чего создаются онлайн-чаты?

Основным назначением чатов выступает создание дополнительного канала быстрой и удобной связи с посетителями сайта. В том числе – с целью увеличения трафика, объемов продаж и других подобных показателей.

Какие требования предъявляются к чату в современных условиях?

Качественно разработанный онлайн-чат должен соответствовать трем обязательным требованиям: корректная работа на любых устройствах, отображение новых сообщений без необходимости обновления страницы, достаточный для удобного и интересного общения функционал.

Как создать онлайн-чат самостоятельно?

Чтобы сделать это, необходимо сначала написать каркаса чата (обычно – с применением HTML), а затем добавить к нему функционал (в этом случае чаще всего используются PHP и JavaScript).

Можно ли воспользоваться готовыми решениями?

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

Подведем итоги

  1. Онлайн-чат – удобный, доступный и бюджетный способ создать новый канал связи с посетителями сайта, благодаря чему повысить продажи, поднять уровень трафика или увеличить лояльность к интернет-ресурсу.
  2. Современные требования к чату – корректная работа на разных устройствах, интеграция с социальными сетями и мессенджерами, появление новых сообщений без необходимости обновлять страницу, дополнительные опции в виде смайликов и т.д.
  3. Простой чат вполне реально разработать самостоятельно – с использованием базовых знаний по программированию на HTML, PHP и JavaScript (возможные и другие варианты по языкам разработки).
  4. Альтернативный способ решения задачи – приобретение готового онлайн-чата с последующей настройкой под запросы пользователя.

Создание мини-чата на PHP и jQuery

От автора: В данной обучающей статье мы с вами научимся создавать мини-чат на PHP и jQuery, который позволит посетителям вашего сайта оставлять друг другу небольшие комментарии. Сообщения будут храниться на стороне сервера в виде файлов, никакой базы данных, например, MySQL не потребуется. Для облегчения работы мы будем использовать две PHP библиотеки – Flywheel для хранения сообщений в виде файлов в формате JSON и RelativeTime для создания относительных временных меток в удобочитаемом для человека виде. Для установки данных библиотек будет использоваться Composer.

скачать исходникидемо

На стороне клиента мы будем использовать обычный jQuery код и библиотеку Emoji One, которая является бесплатной и служит для добавления симпатичных смайликов-эмоджи в веб-приложения. Давайте начинать!

Запускаем мини-чат

Вы можете скачать исходники по вышеприведенной ссылке. В исходном коде содержится много комментариев, и весь код легко читается. Для запуска нужно загрузить исходный код на хостинг или добавить его в папку htdocs сервера Apache, если вы пользуетесь чем-нибудь вроде XAMPP или MAMP. Затем наберите в вашем браузере адрес localhost (или адрес вашего сайта, если вы загрузили исходники на хостинг). Вот несколько моментов, на которые следует обратить внимание:

В zip архивах уже содержатся необходимые зависимости, поэтому вам не нужно устанавливать Composer. Так гораздо проще начать работать с кодом – просто загрузите и используйте!

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

Убедитесь в том, что директория для хранения данных/сообщений существует и доступна для записи. В противном случае вы увидите сообщения об ошибках в вашем лог-файле, и сообщения не будут сохранены. Возможно, вам потребуется изменить права директории на 777 с помощью команды chmod, если ошибки будут продолжать появляться.

HTML

Давайте начнем с файла index.html. Это обычный HTML5 документ, который включает в себя наши JavaScript библиотеки, скрипты и таблицы стилей. Вот код, относящийся непосредственно к мини-чату:

index.html

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<div class=«shoutbox»>

    <h1>Shout box <img src=‘./assets/img/refresh.png’/></h1>

    <ul class=«shoutbox-content»></ul>

    <div class=«shoutbox-form»>

        <h2>Write a message <span>×</span></h2>

        <form action=«./publish.php» method=«post»>

            <label for=«shoutbox-name»>nickname </label> <input type=«text» id=«shoutbox-name» name=«name»/>

            <label class=«shoutbox-comment-label» for=«shoutbox-comment»>message </label> <textarea id=«shoutbox-comment» name=«comment» maxlength=‘240’></textarea>

            <input type=«submit» value=«Shout!»/>

        </form>

    </div>

</div>

С помощью JavaScript мы поместим опубликованные сообщения внутрь элемента ul. По умолчанию форма скрыта и появляется только при клике на заголовок “Write a message” («Написать сообщение»).

JavaScript

А вот наш файл script.js, который заставляет работать вышеприведенный HTML:

assets/js/script.js

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

$(function(){

    // Сохраняем некоторые элементы в переменные для удобства

    var refreshButton = $(‘h1 img’),

        shoutboxForm = $(‘.shoutbox-form’),

        form = shoutboxForm.find(‘form’),

        closeForm = shoutboxForm.find(‘h2 span’),

        nameElement = form.find(‘#shoutbox-name’),

        commentElement = form.find(‘#shoutbox-comment’),

        ul = $(‘ul.shoutbox-content’);

    // Заменяем :) на смайлики-эмоджи:

    emojione.ascii = true;

    // Загружаем комментарии.

    load();

    // При отправке формы, если все заполнено, публикуем сообщение в базе данных

    var canPostComment = true;

    form.submit(function(e){

        e.preventDefault();

        if(!canPostComment) return;

        var name = nameElement.val().trim();

        var comment = commentElement.val().trim();

        if(name.length && comment.length && comment.length < 240) {

            publish(name, comment);

            // Блокируем публикацию новых сообщений

            canPostComment = false;

            // Разрешаем новому комментарию быть опубликованным через 5 секунд

            setTimeout(function(){

                canPostComment = true;

            }, 5000);

        }

    });

    // Переключаем видимость формы.

    shoutboxForm.on(‘click’, ‘h2’, function(e){

        if(form.is(‘:visible’)) {

            formClose();

        }

        else {

            formOpen();

        }

    });

    // При клике на кнопку REPLY (Ответить) происходит добавление в текстовое поле имени человека, которому вы хотели бы ответить.

    ul.on(‘click’, ‘.shoutbox-comment-reply’, function(e){

        var replyName = $(this).data(‘name’);

        formOpen();

        commentElement.val(‘@’+replyName+‘ ‘).focus();

    });

    // При клике на кнопку «Обновить» происходит срабатывание функции load

    var canReload = true;

    refreshButton.click(function(){

        if(!canReload) return false;

        load();

        canReload = false;

        // Разрешаем дополнительные перезагрузки через 2 секунды

        setTimeout(function(){

            canReload = true;

        }, 2000);

    });

    // Автоматически обновляем сообщения каждые 20 секунд

    setInterval(load,20000);

    function formOpen(){

        if(form.is(‘:visible’)) return;

        form.slideDown();

        closeForm.fadeIn();

    }

    function formClose(){

        if(!form.is(‘:visible’)) return;

        form.slideUp();

        closeForm.fadeOut();

    }

    // Сохраняем сообщение в базе данных

    function publish(name,comment){

        $.post(‘publish.php’, {name: name, comment: comment}, function(){

            nameElement.val(«»);

            commentElement.val(«»);

            load();

        });

    }

    // Получаем последние сообщения

    function load(){

        $.getJSON(‘./load.php’, function(data) {

            appendComments(data);

        });

    }

    // Обрабатываем массив с сообщениями в виде HTML

    function appendComments(data) {

        ul.empty();

        data.forEach(function(d){

            ul.append(‘<li>’+

                ‘<span class=»shoutbox-username»>’ + d.name + ‘</span>’+

                ‘<p class=»shoutbox-comment»>’ + emojione.toImage(d.text) + ‘</p>’+

                ‘<div class=»shoutbox-comment-details»><span class=»shoutbox-comment-reply» data-name=»‘ + d.name + ‘»>REPLY</span>’+

                ‘<span class=»shoutbox-comment-ago»>’ + d.timeAgo + ‘</span></div>’+

            ‘</li>’);

        });

    }

});

У библиотеки Emoji One есть версии и для JavaScript и для PHP. В методе appendComments мы используем функцию emojione.toImage(), чтобы сконвертировать все напечатанные смайлы в смайлики-эмоджи. Загляните на этот полезный сайт emoji.codes. Теперь фронтенд готов. Давайте переходить к бэкенду.

PHP

У нас есть два файла – publish.php и load.php. Первый принимает POST запрос, чтобы сохранить сообщения в базе данных, а второй возвращает 20 последних сообщений. Эти файлы не вызываются напрямую посетителями сайта, а только обрабатывают AJAX запросы.

publish.php

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

<?php

// Подключение наших библиотек

require ‘vendor/autoload.php’;

// Настраиваем хранилище данных

$dir = __DIR__.‘/data’;

$config = new JamesMossFlywheelConfig($dir, array(

    ‘formatter’ => new JamesMossFlywheelFormatterJSON,

));

$repo = new JamesMossFlywheelRepository(‘shouts’, $config);

// Сохраняем поступившие данные (сообщения) в хранилище данных

if(isset($_POST[«name»]) && isset($_POST[«comment»])) {

    $name = htmlspecialchars($_POST[«name»]);

    $name = str_replace(array(«n», «r»), », $name);

    $comment = htmlspecialchars($_POST[«comment»]);

    $comment = str_replace(array(«n», «r»), », $comment);

    // Сохранение нового сообщения

    $shout = new JamesMossFlywheelDocument(array(

        ‘text’ => $comment,

        ‘name’ => $name,

        ‘createdAt’ => time()

    ));

    $repo>store($shout);

}

Здесь мы напрямую используем упомянутую вначале библиотеку Flywheel. Как только она будет настроена, вы можете хранить любые типы данных, которые будут записаны в виде JSON файла в директории data/shouts. Чтение данных сообщений происходит в load.php:

load.php

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

<?php

require ‘vendor/autoload.php’;

// Если вы хотите удалить старые сообщения, измените значение на true. Мы так сделали для очистки демо-примера.

$deleteOldComments = false;

// Настройка хранилища данных

$dir = __DIR__.‘/data’;

$config = new JamesMossFlywheelConfig($dir, array(

    ‘formatter’ => new JamesMossFlywheelFormatterJSON,

));

$repo = new JamesMossFlywheelRepository(‘shouts’, $config);

// Удаляем комментарии, опубликованные больше 1 часа назад, если в переменной содержится true.

if($deleteOldComments) {

    $oldShouts = $repo>query()

                >where(‘createdAt’, ‘<‘, strtotime(‘-1 hour’))

                >execute();

    foreach($oldShouts as $old) {

        $repo>delete($old>id);

    }

}

// Отправляем последние 20 сообщений в формате json

$shouts = $repo>query()

        >orderBy(‘createdAt ASC’)

        >limit(20,0)

        >execute();

$results = array();

$config = array(

    ‘language’ => ‘RelativeTimeLanguagesEnglish’,

    ‘separator’ => ‘, ‘,

    ‘suffix’ => true,

    ‘truncate’ => 1,

);

$relativeTime = new RelativeTimeRelativeTime($config);

foreach($shouts as $shout) {

    $shout>timeAgo = $relativeTime>timeAgo($shout>createdAt);

    $results[] = $shout;

}

header(‘Content-type: application/json’);

echo json_encode($results);

Мы добавили код, который удаляет комментарии, опубликованные больше 1 часа назад. Мы используем данную возможность, чтобы не загромождать демо-пример. Вы можете также включить ее при желании. После выбора сообщений мы также высчитываем относительную временную метку в удобочитаемом для человека виде с помощью библиотеки RelativeTime.

Теперь наш мини-чат готов! Вы можете добавить его на ваш веб-сайт, настроить или переделать его так, как вам захочется. Надеемся, что он вам понравился!

Автор: Nick Anastasov

Источник: //tutorialzine.com/

Редакция: Команда webformyself.

JavaScript. Быстрый старт

Изучите основы JavaScript на практическом примере по созданию веб-приложения

Узнать подробнее

Разработка веб-приложения на PHP

Скачайте видеокурс и узнайте, как создать веб-приложение на PHP

Скачать

Как создать приложение-чат за двадцать минут

Время на прочтение
11 мин

Количество просмотров 18K

image

Мой отец любит напоминать мне, что, будучи компьютерным инженером в 1970-х, «он был программистом до того, как программирование стало модным». Пару раз он даже показывал старые скрипты Fortran и COBOL. Прочитав этот код, я с уверенностью могу сказать, что программирование сегодня определенно круче.

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

Сравнением, позволяющим продемонстрировать эволюцию разработки программного обеспечения, является строительство. Когда-то строительство любого дома начиналось с вырубки деревьев на вашем участке. Однако быстро появились материалы, инструменты и способы, чтобы строительство завершалось быстрее, объекты становились прочнее, а рабочие освобождались от некоторых элементарных задач.

Сколько было бы построено небоскребов, если бы строители сами добывали себе сталь?

Разработчики ПО, которые продолжают работать и по сей день, на заре карьеры сами “рубили себе деревья”. При этом беспрецедентные инновации последнего десятилетия привели к тому, что индустрия программного обеспечения стала развиваться примерно так же, как и строительство.

Проще говоря, у современных разработчиков теперь есть инструменты, техника и передовые методы, которые позволяют быстрее завершать проекты, получать стабильные приложения, а так же избавляют разработчиков от задач низкого уровня.

Как сделать приложение для чата

Давайте быстро создадим что-нибудь, что раньше занимало бы дни или недели. Мы сделаем Public Chat Room приложение, которое использует WebSockets для обмена сообщениями в реальном времени.

WebSockets нативно поддерживаются всеми современными браузерами. Однако наша цель — выяснить, какие инструменты мы можем использовать в работе, а не изобретать их. Учитывая это, мы будем использовать следующие технологии:

  • 8base —  управляемый GraphQL API
  • VueJS — JavaScript фреймворк

Стартовый проект и полный файл README можно найти в этом репозитории GitHub. Если вы хотите просмотреть только готовое приложение, загляните в ветку public-chat-room.

Кроме того, в видео ниже (на английском языке) более подробно объясняется каждый шаг.

Начнем.

Семь шагов для создания чат приложения:

1. Настройка проекта

Клонируйте стартовый проект и перейдите в директорию группового чата. Вы можете сами определить, использовать yarn или npm для установки зависимостей проекта. В любом случае, нам нужны все NPM пакеты, обозначенные в файле package.json.

# Клонируем проект
git clone https://github.com/8base/Chat-application-using-GraphQL-Subscriptions-and-Vue.git group-chat
# Переходим в директорию
cd group-chat
# Устанавливаем зависимости
yarn

Чтобы взаимодействовать с GraphQL API, мы должны настроить три переменные среды. Создайте файл .env.local в корневой директории с помощью следующей команды, и приложение Vue после инициализации автоматически установит переменные среды, которые мы добавили в этот файл.

echo 'VUE_APP_8BASE_WORKSPACE_ID=<YOUR_8BASE_WORKSPACE_ID>
VUE_APP_8BASE_API_ENDPOINT=https://api.8base.com
VUE_APP_8BASE_WS_ENDPOINT=wss://ws.8base.com'
> .env.local

Оба значения VUE_APP_8BASE_API_ENDPOINT и VUE_APP_8BASE_WS_ENDPOINT менять не нужно. Необходимо только установить значение VUE_APP_8BASE_WORKSPACE_ID.

Если у вас есть воркспейс 8base, который вы хотите использовать для создания чат-приложения по нашему руководству, обновите файл .env.local, указав свой идентификатор воркспейса. Если нет — получите идентификатор воркспейса, выполнив шаги 1 и 2 из 8base Quickstart.

2. Импорт схемы

Теперь нам нужно подготовить серверную часть. В корне этого репозитория вы должны найти файл chat-schema.json. Чтобы импортировать его в рабочую область, нужно просто установить командную строку 8base и залогиниться, а затем импортировать файл схемы.

# Установка 8base CLI
yarn global add 8base-cli
# Аутентификация CLI
8base login
# Импортируем схему в нашу рабочую область
8base import -f chat-schema.json -w <YOUR_8BASE_WORKSPACE_ID>

3. Доступ к API

Последняя задача по бэкенду — разрешить публичный доступ к GraphQL API.

В консоли 8base перейдите в App Services > Roles > Guest. Обновите разрешения, установленные как для сообщений, так и для пользователей, чтобы они были или отмечены галочкой, или установлены как All Records (как показано на скриншоте ниже).

Роль Guest определяет, что разрешено делать пользователю, отправившему неаутентифицированный запрос к API.

image
Редактор ролей в консоли 8base.

4. Пишем GraphQL запросы

На этом этапе мы собираемся определить и выписать все запросы GraphQL, которые нам понадобятся для нашего компонента чата. Это поможет нам понять, какие данные мы будем читать, создавать и прослушивать (через WebSockets) с помощью API.

Следующий код следует поместить в файл src / utils / graphql.js. Прочтите комментарии над каждой экспортированной константой, чтобы понять, что выполняет каждый запрос.


/* gql преобразует строки запроса в документы graphQL */
import gql from "graphql-tag";
‍
/* 1. Получение всех пользователей онлайн-чата и последних 10 сообщений */
export const InitialChatData = gql`
{
  usersList {
    items {
      id
      email
    }
  }
  messagesList(last: 10) {
    items {
      content
      createdAt
      author {
        id
        email
      }
    }
  }
}
`;
‍
/* 2. Создание новых пользователей чата и назначение им роли гостя */
export const CreateUser = gql`
mutation($email: String!) {
  userCreate(data: { email: $email, roles: { connect: { name: "Guest" } } }) {
    id
  }
}
`;
‍
/* 3. Удаление пользователя чата*/
export const DeleteUser = gql`
mutation($id: ID!) {
  userDelete(data: { id: $id, force: true }) {
    success
  }
}
`;
‍
/* 4. Подписка на создание и удаление пользователей чата */
export const UsersSubscription = gql`
subscription {
  Users(filter: { mutation_in: [create, delete] }) {
    mutation
    node {
      id
      email
    }
  }
}
`;
‍
/* 5. Создание новых сообщений чата и связывание их с автором */
export const CreateMessage = gql`
mutation($id: ID!, $content: String!) {
  messageCreate(
    data: { content: $content, author: { connect: { id: $id } } }
  ) {
    id
  }
}
`;
‍
/* 6. Подписка на создание сообщений чата. */
export const MessagesSubscription = gql`
subscription {
  Messages(filter: { mutation_in: create }) {
    node {
      content
      createdAt
      author {
        id
        email
      }
    }
  }
}
`;

5. Настройка Apollo клиента для подписок

Когда наши запросы GraphQL написаны, самое время настроить наши модули API.

Во-первых, давайте займемся клиентом API с помощью ApolloClient с его обязательными настройками по умолчанию. Для createHttpLink мы предоставляем наш полностью сформированный эндпоинт воркспейса. Этот код находится в src/utils/api.js.

import { ApolloClient } from "apollo-boost";
import { createHttpLink } from "apollo-link-http";
import { InMemoryCache } from "apollo-cache-inmemory";
‍
const { VUE_APP_8BASE_API_ENDPOINT, VUE_APP_8BASE_WORKSPACE_ID } = process.env;

export default new ApolloClient({
link: createHttpLink({
  uri: `${VUE_APP_8BASE_API_ENDPOINT}/${VUE_APP_8BASE_WORKSPACE_ID}`,
}),
cache: new InMemoryCache(),
});

// Note: Чтобы узнать больше о параметрах, доступных при настройке // ApolloClient, обратитесь к их документации.

Затем займемся клиентом подписки, используя subscriptions-transport-ws и isomorphic-ws. Этот код немного длиннее, чем предыдущий, поэтому стоит потратить время на чтение комментариев в коде.

Мы инициализируем SubscriptionClient, используя наш эндопоинт WebSockets и workspaceId в параметрах connectionParams. Затем мы используем этот subscriptionClient в двух методах, определенных в экспорте по умолчанию: subscribe() и close().

subscribe позволяет нам создавать новые подписки с обратными вызовами данных и ошибок. Метод close — это то, что мы можем использовать, чтобы закрыть соединение при выходе из чата.

import WebSocket from "isomorphic-ws";
import { SubscriptionClient } from "subscriptions-transport-ws";
‍
const { VUE_APP_8BASE_WS_ENDPOINT, VUE_APP_8BASE_WORKSPACE_ID } = process.env;

/**
* Создайте клиент подписки, используя соответствующие
*переменные среды и параметры по умолчанию.
*/

const subscriptionClient = new SubscriptionClient(
VUE_APP_8BASE_WS_ENDPOINT,
{
  reconnect: true,
  connectionParams: {
    /**
      * Workspace ID ОБЯЗАТЕЛЬНО должен быть установлен, иначе 
*конечная точка Websocket не сможет
*сопоставить запрос с соответствующим воркспейсом
      */
    workspaceId: VUE_APP_8BASE_WORKSPACE_ID,
  },
},
/**
  * Конструктор для реализации WebSocket, совместимой с W3C. *Используйте это, если ваше окружение не имеет встроенного собственного *WebSocket (например, с клиентом NodeJS)
  */
WebSocket
);
‍
export default {
/**
  * Принимает запрос подписки, любые переменные и обработчики колбэков *'data’ и 'error’
  */
subscribe: (query, options) => {
  const { variables, data, error } = options;
‍
  /**
    * Запускает новый запрос на подписку.
    */
  const result = subscriptionClient.request({
    query,
    variables,
  });
‍
  /**
    * Функцию отписки можно использовать для закрытия *определенной подписки, в отличие от ВСЕХ подписок, 
*поддерживаемых subscriptionClient
    */
  const { unsubscribe } = result.subscribe({
    /**
      * При получении события результат передается в 
*колбэк данных, указанный разработчиком.
      */
    next(result) {
      if (typeof data === "function") {
        data(result);
      }
    },
    /**
      * Каждый раз при получении ошибки она передается в колбэк ошибок, указанный разработчиком.
      */
    error(e) {
      if (typeof error === "function") {
        error(e);
      }
    },
  });
‍
  return unsubscribe;
},
‍
/**
  * Закрывает subscriptionClient соединение.
  */
close: () => {
  subscriptionClient.close();
},
};
// Примечание. Чтобы узнать больше о SubscriptionClient и его параметрах, 
// пожалуйста, обратитесь к их документации.

6. Написание компонента Vue

Теперь у нас есть все необходимое для создания публичного чата. Осталось только написать один компонент GroupChat.vue.

Загрузите компонент с помощью yarn serve, и продолжим.

Важное замечание: у каждого свое представление о красоте, поэтому я сделал только минимальные стили, необходимые для того, чтобы компонент был функциональным.

Скрипт компонента

Сначала нам нужно импортировать наши модули, простые стили и GraphQL запросы. Всё это находится в нашем каталоге src / utils.
Объявите следующие импорты в GroupChat.vue.

/* API модули */
import Api from "./utils/api";
import Wss from "./utils/wss";

/* graphQL операции */
import {
InitialChatData,
CreateUser,
DeleteUser,
UsersSubscription,
CreateMessage,
MessagesSubscription,
} from "./utils/graphql";
‍
/* Стили */
import "../assets/styles.css";

Компонентные данные

Мы можем определить, какие свойства данных мы хотим использовать в функции data нашего компонента. Все, что нам нужно, это способ хранить пользователей чата, сообщения, имя «текущего» пользователя и любое сообщение, которое еще не было отправлено. Эти свойства можно добавить следующим образом:

/* imports ... */

export default {
name: "GroupChat",
‍
data: () => ({
  messages: [],
  newMessage: "",
  me: { email: "" },
  users: [],
}),
};

Хуки жизненного цикла

Наши хуки жизненного цикла выполняются в разные моменты «жизни» компонента Vue. Например, когда он монтируется или обновляется. В данном случае нас интересует только создание и beforeDestroy компонента. В таких случаях мы хотим либо открыть подписки на чат, либо закрыть.

/* ипорты... */

export default {
/* остальные параметры ... */

/**
  * Хук жизненного цикла, выполняющийся при создании компонента.
  */
created() {
  /**
    * Подписка на событие, которое срабатывает при создании или удалении пользователя
    */
  Wss.subscribe(UsersSubscription, {
    data: this.handleUser,
  });
  /**
    * Подписка на событие, которое срабатывает при создании сообщения
    */
  Wss.subscribe(MessagesSubscription, {
    data: this.addMessage,
  });
  /**
    * Получение начальные данные чата (пользователи и последние 10 сообщений)
    */
  Api.query({
    query: InitialChatData,
  }).then(({ data }) => {
    this.users = data.usersList.items;
    this.messages = data.messagesList.items;
  });
  /**
    * Колбэк вызывается при обновлении страницы, чтобы закрыть чат
    */
  window.onbeforeunload = this.closeChat;
},
‍
/**
  * Хук жизненного цикла, выполняющийся при уничтожении компонента.
  */
beforeDestroy() {
  this.closeChat();
},
};

Методы компонента

Мы должны добавить определенные методы, предназначенные для обработки каждого вызова / ответа API (createMessage, addMessage, closeChat, и т.д.). Все они будут сохранены в объекте методов нашего компонента.

Следует отметить одну вещь: большинство мутаций не ждут и не обрабатывают ответы. Это происходит потому, что у нас работают подписки, которые отслеживают эти мутации. После успешного запуска данные о событиях обрабатываются именно подпиской.

Большинство этих методов говорят сами за себя. В любом случае, прочтите комментарии в следующем коде.

/* импорты ... */

export default {
/* остальные параметры ... */
‍
methods: {
  /**
    * Создание нового пользователя, используя указанный адрес электронной почты.
    */
  createUser() {
    Api.mutate({
      mutation: CreateUser,
      variables: {
        email: this.me.email,
      },
    });
  },
  /**
    * Удалиние пользователя по его ID.
    */
  deleteUser() {
    Api.mutate({
      mutation: DeleteUser,
      variables: { id: this.me.id },
    });
  },
  /**
    * Наши пользователи подписываются на события создания и обновления, и поэтому 
*нам нужно выбрать соответствующий метод для обработки ответа в зависимости от 
*типа мутации.
*
*Здесь у нас есть объект, который ищет тип мутации по имени, возвращает 
*его и выполняет функцию, передавая узел события.
    */
  handleUser({
    data: {
      Users: { mutation, node },
    },
  }) {
    ({
      create: this.addUser,
      delete: this.removeUser,
    }[mutation](node));
  },
  /**
    * Добавляет нового пользователя в массив users, сначала проверяя, *является ли добавляемый пользователь текущим пользователем.
    */
  addUser(user) {
    if (this.me.email === user.email) {
      this.me = user;
    }
    this.users.push(user);
  },
  /**
    * Удаляет пользователя из массива users по ID.
    */
  removeUser(user) {
    this.users = this.users.filter(
      (p) => p.id != user.id
    );
  },
  /* Создать новое сообщение */
  createMessage() {
    Api.mutate({
      mutation: CreateMessage,
      variables: {
        id: this.me.id,
        content: this.newMessage,
      },
    }).then(() => (this.newMessage = ""));
  },
  /**
    * Наша подписка на сообщения проверяет только событие создания.  *Поэтому все, что нам нужно сделать, это поместить его в наш массив *сообщений.
    */
  addMessage({
    data: {
      Messages: { node },
    },
  }) {
    this.messages.push(node);
  },
  /**
    * Мы хотим закрыть наши подписки и удалить пользователя. Этот метод можно вызвать в нашем хуке жизненного цикла beforeDestroy и любом другом соответствующем колбэке.
    */
  closeChat () {
    /* Закрытие подписки перед выходом */
    Wss.close()
    /* Удаление участника */
    this.deleteUser();
    /* Установка значения по умолчанию */
    this.me = { me: { email: '' } }
  }
},
‍
/* Хуки ... */
}

Шаблон компонента

И последнее, но не менее важное: у нас есть компонент GroupChat.vue.

Есть тысячи отличных руководств о том, как создавать красивые пользовательские интерфейсы. Это — не одно из них.

Следующий шаблон соответствует минимальным требованиям для чат-приложения. Делать его красивым или нет — это уже ваше дело. Тем не менее, давайте быстро пройдемся по ключевой разметке, которую мы здесь реализовали.

Как всегда, читайте встроенные комментарии к коду.

<template>
<div id="app">
  <!--
    Представление чата должно отображаться только в том случае, если текущий пользователь имеет идентификатор. В противном случае отображается форма регистрации..
    -->
  <div v-if="me.id" class="chat">
    <div class="header">
      <!--
        Поскольку мы используем подписки, которые работают в режиме реального времени, количество пользователей, которые сейчас находятся в сети, будет динамически корректироваться.
        -->
      {{ users.length }} Online Users
      <!--
       Пользователь может выйти из чата, вызвав функцию closeChat..
        -->
      <button @click="closeChat">Leave Chat</button>
    </div>
    <!--
    Каждое сообщение, которое мы храним в массиве сообщений, мы будем отображать в этом div. Кроме того, если идентификатор участника сообщения совпадает с идентификатором текущего пользователя, мы присвоим ему класс me.
      -->
    <div
      :key="index"
      v-for="(msg, index) in messages"
      :class="['msg', { me: msg.participant.id === me.id }]"
    >
      <p>{{ msg.content }}</p>
      <small
        ><strong>{{ msg.participant.email }}</strong> {{ msg.createdAt
        }}</small
      >
    </div>
    <!--
Инпут сообщения привязан к свойству данных newMessage.
      -->
    <div class="input">
      <input
        type="text"
        placeholder="Say something..."
        v-model="newMessage"
      />
      <!--
       Когда пользователь нажимает кнопку отправки, мы запускаем функцию createMessage.
        -->
      <button @click="createMessage">Send</button>
    </div>
  </div>
  <!--
   Процесс регистрации просит пользователя ввести адрес электронной почты. Как только инпут теряет фокус, вызывается метод createUser.
    -->
  <div v-else class="signup">
    <label for="email">Sign up to chat!</label>
    <br />
    <input
      type="text"
      v-model="me.email"
      placeholder="What's your email?"
      @blur="createUser"
      required
    />
  </div>
</div>
</template>

И вот публичный чат построен. Если вы откроете его в своей локальной сети, вы сможете начать отправлять и получать сообщения. Однако, чтобы доказать, что это настоящий групповой чат, откройте несколько окон и наблюдайте за ходом разговора.

7. Заключение и тестирование

В этом руководстве мы изучили, как использование современных инструментов разработки позволяет нам создавать реальные приложения за считанные минуты.

Надеюсь, вы также узнали, как инициализировать ApolloClient и SubscriptionClient для эффективного выполнения запросов GraphQL, мутаций и подписок в воркспейсе 8base, а также немного о VueJS.

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

Создайте чат-приложение с 8base

8base — это готовый к работе бессерверный бэкенд-как-сервис, созданный разработчиками для разработчиков. Платформа 8base позволяет разработчикам создавать потрясающие облачные приложения с использованием JavaScript и GraphQL. Узнайте больше о платформе 8base здесь.

В этом уроке мы будем создавать простое приложение веб-чата с помощью PHP и jQuery. Утилита такого типа прекрасно подойдет для системы онлайн-поддержки вашего сайта.


Введение

final productfinal productfinal product

Приложение чата, которое мы сегодня построим, будет довольно простым.  Оно будет включать в себя систему входа и выхода, возможности в AJAX-стиле, а также предложит поддержку нескольких пользователей.


Шаг 1: HTML разметка

Мы начнем этот урок с создания нашего первого файла index.php.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Chat - Customer Module</title>
<link type="text/css" rel="stylesheet" href="style.css" />
</head>

<div id="wrapper">
  <div id="menu">
		<p class="welcome">Welcome, <b></b></p>
		<p class="logout"><a id="exit" href="#">Exit Chat</a></p>
		<div style="clear:both"></div>
	</div>
	
	<div id="chatbox"></div>
	
	<form name="message" action="">
		<input name="usermsg" type="text" id="usermsg" size="63" />
		<input name="submitmsg" type="submit"  id="submitmsg" value="Send" />
	</form>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
// jQuery Document
$(document).ready(function(){

});
</script>
</body>
</html>
  • Мы начнем наш html с обычных DOCTYPE, html, head, и body тагов. В таг head мы добавим наш заголовок и ссылку на нашу таблицу стилей css (style.css).
  • Внутри тага body, мы структурируем наш макет внутри блока — обертки #wrapper div. У нас будет три главных блока: простое меню, окно чата и поле ввода нашего сообщения; каждый со своим соответствующим div и id.
    • Блок меню #menu div будет состоять из двух абзацев. Первый будет приветствием пользователю и поплывет налево, а второй будет ссылкой на выход и поплывет направо. Мы также включим блок div для очистки элементов.
    • Блок чата #chatbox div будет содержать лог нашего чата.  Мы будем загружать наш лог из внешнего файла с использованием ajax-запроса jQuery.  
    • Последним пунктом в нашем блоке-обертке #wrapper div будет наша форма, которая будет включать в себя текстовое поле ввода для сообщения пользователя и кнопку отправки.
  • Мы добавляем наши скрипты последними, чтобы грузить страницу быстрее. Сначала мы вставим ссылку Google jQuery CDN, так как в этом уроке мы будем использовать библиотеку jQuery. Наш второй таг скрипта будет там, где мы будем работать. Мы загрузим весь наш код после того, как документ будет готов.

Шаг 2: Создание стиля CSS

Теперь мы добавим немного css, чтобы заставить наше приложение чата выглядеть лучше, чем стиль браузера по умолчанию. Код, указанный ниже будет добавлен в наш файл style.css.

 
/* CSS Document */
body {
	font:12px arial;
	color: #222;
	text-align:center;
	padding:35px; }
 
form, p, span {
	margin:0;
	padding:0; }
 
input { font:12px arial; }
 
a {
	color:#0000FF;
	text-decoration:none; }
 
	a:hover { text-decoration:underline; }
 
#wrapper, #loginform {
	margin:0 auto;
	padding-bottom:25px;
	background:#EBF4FB;
	width:504px;
	border:1px solid #ACD8F0; }
 
#loginform { padding-top:18px; }
 
	#loginform p { margin: 5px; }
 
#chatbox {
	text-align:left;
	margin:0 auto;
	margin-bottom:25px;
	padding:10px;
	background:#fff;
	height:270px;
	width:430px;
	border:1px solid #ACD8F0;
	overflow:auto; }
 
#usermsg {
	width:395px;
	border:1px solid #ACD8F0; }
 
#submit { width: 60px; }
 
.error { color: #ff0000; }
 
#menu { padding:12.5px 25px 12.5px 25px; }
 
.welcome { float:left; }
 
.logout { float:right; }
 
.msgln { margin:0 0 2px 0; }

В вышеуказанном css нет ничего особенного, кроме того факта, что некоторые id или классы, для которых мы устанавливаем стиль, будут добавлены немного позже.

Как вы можете видеть выше, мы закончили строить пользовательский интерфейс чата.

Шаг 3: Используем PHP, чтобы создать форму входа.

Теперь мы реализуем простую форму, которая будет спрашивать у пользователя его имя, перед тем, как пустить его дальше.

<?
session_start();

function loginForm(){
	echo'
	<div id="loginform">
	<form action="index.php" method="post">
		<p>Please enter your name to continue:</p>
		<label for="name">Name:</label>
		<input type="text" name="name" id="name" />
		<input type="submit" name="enter" id="enter" value="Enter" />
	</form>
	</div>
	';
}

if(isset($_POST['enter'])){
	if($_POST['name'] != ""){
		$_SESSION['name'] = stripslashes(htmlspecialchars($_POST['name']));
	}
	else{
		echo '<span class="error">Please type in a name</span>';
	}
}
?>

Функция loginForm(), которую мы создали, состоит из простой формы входа, которая спрашивает у пользователя его/ее имя. Затем мы используем конструкцию if else, чтобы проверить, ввел ли пользователь имя. Если человек ввел имя, мы устанавливаем его, как $_SESSION[‘имя’]. Так как мы используем сессию, основанную на cookie, чтобы хранить имя, мы должны вызвать session_start() перед тем, как что-нибудь выводить в браузер.

Есть одна вещь, на которую вы возможно захотите обратить особое внимание — то, что мы использовали функцию htmlspecialchars(), которая конвертирует специальные символы в HTML сущности, тем самым защищая имя переменной, чтобы оно не стало жертвой межсайтового скриптинга (XSS). Мы также добавим эту функцию позже к текстовой переменной, которая будет опубликована в логе чата.

Отображение формы входа

Для того, чтобы показать форму логина в случае, если пользователь не вошел в систему, и следовательно, не сессия не создалась, мы используем другую инструкцию if else вокруг блока-обертки #wrapper div и тагов скрипта в нашем исходном коде. В противоположном случае, если пользователь вошел в систему и создал сессию, этот код спрячет форму входа и покажет окно чата.

<?php
if(!isset($_SESSION['name'])){
	loginForm();
}
else{
?>
<div id="wrapper">
	<div id="menu">
		<p class="welcome">Welcome, <b><?php echo $_SESSION['name']; ?></b></p>
		<p class="logout"><a id="exit" href="#">Exit Chat</a></p>
		<div style="clear:both"></div>
	</div>	
	<div id="chatbox"></div>
	
	<form name="message" action="">
		<input name="usermsg" type="text" id="usermsg" size="63" />
		<input name="submitmsg" type="submit"  id="submitmsg" value="Send" />
	</form>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>
<script type="text/javascript">
// jQuery Document
$(document).ready(function(){
});
</script>
<?php
}
?>

Приветствие и меню выхода из системы

Мы еще не закончили создавать систему входа для этого приложения чата. Нам еще нужно дать пользователю возможность выйти из системы и закончить сессию чата. Как вы помните, наша исходная HTML разметка включала в себя простое меню. Давайте вернемся назад и добавим некоторый PHP код, который придаст меню больше функциональности.

Прежде всего, давайте добавим имя пользователя в сообщение приветствия. Мы сделаем это, выводя сессию имени пользователя.

<p class="welcome">Welcome, <b><?php echo $_SESSION['name']; ?></b></p>

Для того, чтобы позволить пользователю выйти из системы и завершить сессию, мы прыгнем выше головы и кратко используем jQuery.

<script type="text/javascript">
// jQuery Document
$(document).ready(function(){
	//If user wants to end session
	$("#exit").click(function(){
		var exit = confirm("Are you sure you want to end the session?");
		if(exit==true){window.location = 'index.php?logout=true';}		
	});
});
</script>

Код jquery, приведенный выше просто показывает диалог подтверждения, если пользователь кликнет по ссылке выхода #exit. Если пользователь подтвердит выход, тем самым решив закончить сессию, мы отправим его в index.php?logout=true. Это просто создаст переменную с именем logout со значением true. Мы должны перехватить эту переменную с помощью PHP:

if(isset($_GET['logout'])){	
	
	//Simple exit message
	$fp = fopen("log.html", 'a');
	fwrite($fp, "<div class='msgln'><i>User ". $_SESSION['name'] ." has left the chat session.</i><br></div>");
	fclose($fp);
	
	session_destroy();
	header("Location: index.php"); //Redirect the user
}

Теперь мы увидим, существует ли get переменная ‘logout’, используя функцию isset(). Если переменная была передана через url, такой, как ссылка, упомянутая выше, мы переходим к завершению сессии пользователя с текущим именем.

Перед уничтожением сессии пользователя с текущим именем с помощью функции session_destroy() мы хотим выводить простое сообщение о выходе в лог чата. В нем будет сказано, что пользователь покинул сессию чата. Мы сделаем это, используя функции  fopen(), fwrite() и fclose(), чтобы манипулировать нашим файлом log.html, который, как мы увидим позднее, будет создан в качестве лога нашего чата. Пожалуйста, обратите внимание, что мы добавили класс ‘msgln’ в блок div. Мы уж определили стиль css для этого блока.

Проделав это, мы уничтожаем сессию и перенаправляем пользователя на ту же страницу, где появится форма входа в систему.


Шаг 4: Поддержка пользовательского ввода данных

После того, как пользователь подтвердил свои действия в нашей форме, нам нужно захватывать его ввод с клавиатуры и писать его в лог нашего чата. Для того, чтобы сделать это, мы должны использовать jQuery и PHP, чтобы работать синхронно на стороне сервера и на стороне клиента.

jQuery

Практически все, что мы собираемся делать с jQuery для обработки наших данных, будет вращаться вокруг запроса на jQuery post.

	//If user submits the form
	$("#submitmsg").click(function(){	
		var clientmsg = $("#usermsg").val();
		$.post("post.php", {text: clientmsg});				
		$("#usermsg").attr("value", "");
		return false;
	});
  1. Перед тем, как мы что-то начнем делать, мы должны захватить пользовательский ввод, или то, что он напечатал в поток ввода #submitmsg. Этого можно достигнуть функцией val(), которая берет значение, установленное в поле формы. Теперь мы сохраняем это значение в переменную clientmsg.
  2. Вот и наступает самая важная часть: запрос jQuery post. Она отправляет запрос POST в файл post.php, который мы создадим через мгновение. Он отправляет ввод клиента, или то, что было сохранено в переменную clientmsg.
  3. В конце мы очищаем ввод #usermsg, очищая атрибут значения.

Пожалуйста обратите внимание, что код, указанный выше, пойдет в наш таг скрипта, где мы поместили jQuery код выхода из системы.

PHP — post.php

На данный момент мы имеем данные POST, отправляемые в файл post.php каждый раз, когда пользователь отправляет форму и посылает новое сообщение. Наша задача теперь захватить эти данные и записать их в лог нашего чата.

<?
session_start();
if(isset($_SESSION['name'])){
	$text = $_POST['text'];
	
	$fp = fopen("log.html", 'a');
	fwrite($fp, "<div class='msgln'>(".date("g:i A").") <b>".$_SESSION['name']."</b>: ".stripslashes(htmlspecialchars($text))."<br></div>");
	fclose($fp);
}
?>
  1. Прежде чем мы что-либо сделаем, мы должны начать файл post.php с помощью функции session_start(), так как мы будем использовать сессию по имени пользователя в этом файле.
  2. Используя логическую isset, мы проверим, существует ли сессия для ‘name’, перед тем, как что-то делать дальше.
  3. Теперь мы захватим данные POST, которые jQuery послал в этот файл. Мы сохраним эти данные в переменную $text.
  4. Эти данные, так же, как и вообще все данные, вводимые пользователем, будут храниться в файле log.html. Чтобы сделать это, мы откроем файл в режиме ‘a’ функции fopen, который согласно php.net открывает файл только для записи; помещает указатель файла на конец файла. Если файл не существует, попытаемся создать его. Затем мы запишем наше сообщение в файл, используя функцию fwrite().
    • Сообщение, которое мы будем записывать, будет заключено внутри блока .msgln div. Он будет содержать дату и время, сгенерированную функцией date(), сессию имени пользователя и текст, которые также будет окружен функцией htmlspecialchars(), чтобы избежать XSS.

    И наконец, мы закрываем наш файл с помощью fclose().


Шаг 5: Отображение содержимого лога чата (log.html)

Все, что пользователь разместил, обработано и опубликовано с помощью jQuery; оно записано в лог чата с помощью PHP. Единственное, что осталось сделать — это показать обновленный лог чата пользователю.

Чтобы сэкономить нам немного времени, мы предварительно загрузим лог чата в блок #chatbox div, как если бы он что-то содержал.

	<div id="chatbox"><?php
	if(file_exists("log.html") && filesize("log.html") > 0){
		$handle = fopen("log.html", "r");
		$contents = fread($handle, filesize("log.html"));
		fclose($handle);
		
		echo $contents;
	}
	?></div>

Мы используем процедуру, похожую на ту, что мы использовали в файле post.php, но на этот раз мы только читаем и выводим содержимое файла.

Запрос jQuery.ajax

Запрос ajax — это ядро всего, что мы делаем. Этот запрос не только позволяет нам посылать и принимать данные через форму без обновления страницы, но также и позволяет нам обрабатывать запрошенные данные.

//Load the file containing the chat log
	function loadLog(){		

		$.ajax({
			url: "log.html",
			cache: false,
			success: function(html){		
				$("#chatbox").html(html); //Insert chat log into the #chatbox div				
		  	},
		});
	}

Мы завернем наш ajax запрос в функцию. Вы увидите, зачем, прямо сейчас. Как вы можете видеть выше, мы использовали только три из объектов запроса jQuery ajax.

  • url: Строка URL для запроса. Мы используем имя файла лога нашего чата log.html.
  • cache: Это предотвратит кэширование нашего файла. Это обеспечит нам то, что всегда, когда мы посылаем запрос, мы будем иметь обновленный лог чата.
  • sucess: Это позволит нам прикрепить функцию, которая передаст запрошенные нами данные.

Как вы видите, затем мы перемещаем запрошенные нами данные (html) в блок #chatbox div.

Автопрокрутка

Как мы, возможно, видели в других приложениях чатов, содержимое автоматически прокручивается вниз, если контейнер лога чата (#chatbox) переполняется. Мы воплотим простую и похожую возможность, которая будет сравнивать высоту полосы прокрутки контейнера до и после того, как мы выполним ajax запрос. Если высота полосы прокрутки стала больше после запроса, мы используем эффект анимации jQuery, чтобы прокрутить блок #chatbox div.

	//Load the file containing the chat log
	function loadLog(){		
		var oldscrollHeight = $("#chatbox").attr("scrollHeight") - 20; //Scroll height before the request
		$.ajax({
			url: "log.html",
			cache: false,
			success: function(html){		
				$("#chatbox").html(html); //Insert chat log into the #chatbox div	
				
				//Auto-scroll			
				var newscrollHeight = $("#chatbox").attr("scrollHeight") - 20; //Scroll height after the request
				if(newscrollHeight > oldscrollHeight){
					$("#chatbox").animate({ scrollTop: newscrollHeight }, 'normal'); //Autoscroll to bottom of div
				}				
		  	},
		});
	}
  • Сначала мы сохраним высоту полосы прокрутки блока  #chatbox div в переменную oldscrollHeight перед выполнением запроса.
  • После того, как наш запрос вернет успех, мы сохраним высоту полосы прокрутки блока #chatbox div в переменную newscrollHeight.
  • Затем мы сравним высоту полосы прокрутки в обеих переменных, используя конструкцию if. Если newscrollHeight больше, чем oldscrollHeight, мы используем эффект анимации, чтобы прокрутить блок #chatbox div.

Постоянное обновление лога чата

Теперь может возникнуть вопрос, как часто мы будем обновлять новые данные, переданные между пользователями. Или перефразируя вопрос, с какой регулярностью мы будем отправлять постоянные запросы на обновление данных?

setInterval (loadLog, 2500);	//Reload file every 2500 ms or x ms if you wish to change the second parameter

Ответ на наш вопрос находится в функции setInterval. Эта функция будет запускать нашу функцию loadLog() каждые 2,5 секунды, которая будет запрашивать обновленный файл и делать автопрокрутку блока.

Закончили

Мы закончили! Я надеюсь, что вы изучили, как работает базовая система чата, и, если у вас есть какие-либо пожелания, я с радостью их приветствую. Это максимально простая система чата, которую вы можете создать как приложение чата. Вы можете оттолкнуться от нее и построить множественные чат комнаты, добавить админку, эмотиконы и т.д. Здесь ваш предел — это небо.

Ниже привожу несколько ссылок, которые вы возможно захотите посмотреть, если задумаетесь о расширении этого приложения чата:

  • Защитите ваши формы ключами форм — избегайте XSS (межсайтового скриптинга) и подделок межсайтовых запросов.
  • Отправка формы без обновления страницы с использованием jQuery — расширьте наш ajax запрос
  • Как делать AJAX запросы на чистом Javascript  — изучите, как работает кухня запросов на чистом javascript.

  • Следите за нами на Twitter, или подпишитесь на RSS ленту NETTUTS, чтобы получать больше ежедневных уроков и статей по веб-разработке.

Простой чат на JavaScript и PHP

  1. CREATE TABLE IF NOT EXISTS `chat` (
  2. `id` int ( 15 ) NOT NULL AUTO_INCREMENT ,
  3. `name` varchar ( 30 ) NOT NULL ,
  4. `text` text NOT NULL ,
  5. PRIMARY KEY ( `id` )
  6. ) ENGINE = MyISAM DEFAULT CHARSET = cp1251 AUTO_INCREMENT = 1 ;
  1. script type = “text/javascript” src = “js/jquery-1.4.4.min.js” > / script >
  2. script type = “text/javascript” src = “js/jquery.timers.js” > / script >
  3. script type = “text/javascript” src = “js/jquery.cookie.js” > / script >
  1. style >
  2. #msg-box
  3. #msg-box ul
  4. #t-box
  5. / style >
  6. div id = “msg-box” >
  7. ul >
  8. / ul >
  9. / div >
  10. form id = “t-box” action = “?” style = “” >
  11. Имя: input type = “text” class = ‘name’ style = “width:100px;” >
  12. input type = “text” class = ‘msg’ style = “width:500px;” >
  13. input type = “submit” value = “Отправить” style = “margin-top:5px;” >
  14. / form >
  1. //Функции для работы с БД
  2. function getQuery ( $query ) <
  3. $res = mysql_query ( $query ) or die ( mysql_error ( ) ) ;
  4. $row = mysql_fetch_row ( $res ) ;
  5. $var = $row [ 0 ] ;
  6. return $var ;
  7. >
  8. function setQuery ( $query ) <
  9. $res = mysql_query ( $query ) or die ( mysql_error ( ) ) ;
  10. return $res ;
  11. >
  12. //Соединяемся с базой
  13. @ mysql_connect ( ‘localhost’ , ‘root’ , ” ) or die ( “Не могу соединиться с MySQL.” ) ;
  14. @ mysql_select_db ( ‘best’ ) or die ( “Не могу подключиться к базе.” ) ;
  15. @ mysql_query ( ‘SET NAMES utf8;’ ) ;
  16. switch ( $_GET [ “event” ] ) <
  17. //Тут раздаем последние сообщения
  18. case “get” :
  19. //Сколько сообщений раздавать пользователям
  20. $max_message = 60 ;
  21. //Всего сообщений в чате
  22. $count = getQuery ( “SELECT COUNT(`id`) FROM `chat`;” ) ;
  23. //Максимальный ID сообщения
  24. $m = getQuery ( “SELECT MAX(id) FROM `chat` WHERE 1” ) ;
  25. //Удаление лишних сообщений.
  26. //Если хотите, чтобы сохранялась вся история, смело сносите этот кусочек
  27. if ( $count > $max_message ) <
  28. setQuery ( “DELETE FROM `chat` WHERE `id` . ( $m – ( $max_message – 1 ) ) . “;” ) ;
  29. >
  30. //Принимаем от клиента ID последнего сообщения
  31. $mg = $_GET [ ‘id’ ] ;
  32. //Генерируем сколько сообщений нехватает клиенту
  33. if ( $mg == 0 )
  34. if ( $mg 0 )
  35. $msg = array ( ) ;
  36. //Если у клиента не все сообщения, отсылаем ему недостоющие
  37. if ( $mg $m ) <
  38. //Берем из базы недостобщие сообщения
  39. $query = “SELECT * FROM `chat` WHERE `id`>” . $mg . ” AND `id` . $m . ” ORDER BY `id` ” ;
  40. $res = mysql_query ( $query ) or die ( mysql_error ( ) ) ;
  41. while ( $row = mysql_fetch_array ( $res ) ) <
  42. //Заносим сообщения в массив
  43. $msg [ ] = array ( “id” => $row [ ‘id’ ] , “name” => $row [ ‘name’ ] , “msg” => $row [ ‘text’ ] ) ;
  44. >
  45. >
  46. //Отсылаем клиенту JSON с данными.
  47. echo json_encode ( $msg ) ;
  48. break ;
  49. case “set” :
  50. //Принимаем имя.
  51. $name = htmlspecialchars ( $_GET [ ‘name’ ] ) ;
  52. //Принимаем текст сообщения
  53. $msg = htmlspecialchars ( $_GET [ “msg” ] ) ;
  54. //Сохраняем сообщение
  55. setQuery ( “INSERT INTO `chat` (`id` ,`name` ,`text` )VALUES (NULL , ‘” . mysql_real_escape_string ( $name ) . “‘, ‘” . mysql_real_escape_string ( $msg ) . “‘);” ) ;
  56. break ;
  57. >

Как же работает этот скрипт? Сначала, подключается к базе данных. После подключения, смотрим, что запришивает клиент.
Если он запрашивает сообщения, то генерируем сколько сообщений не хватает клиенту. Затем, запрашиваем в безе все необходимые сообщения, добавляем их в массив, генерируем JSON и посылаем все это дело клиенту.

Теперь, у нас есть основа для чата. Все, что нам осталось сделать, так это обновление чата на стороне клиента и добавление новых сообщений в чат. Для всего этого, мы будем использовать Ajax запросы.
Давайте, создадим в файле index.php скрипт для обработки и добавления сообщений.
Добавим между тегов head >. head > наш Javascript:

  1. $ ( function ( ) <
  2. //Если куки с именем не пустые, тащим имя и заполняем форму с именем
  3. if ( $. cookie ( “name” ) != “” )
  4. //Переменная отвечает за id последнего пришедшего сообщения
  5. var mid = 0 ;
  6. //Функция обновления сообщений чата
  7. function get_message_chat ( ) <
  8. //Генерируем Ajax запрос
  9. $. ajaxSetup ( < url : «chat.php» , global : true , type : «GET» , data : «event=get&id=» + mid + «&t=» +
  10. ( new Date ) . getTime ( ) > ) ;
  11. //Отправляем запрос
  12. $. ajax ( <
  13. //Если все удачно
  14. success : function ( msg_j ) <
  15. //Если есть сообщения в принятых данных
  16. if ( msg_j. length > 2 ) <
  17. //Парсим JSON
  18. var obj = JSON. parse ( msg_j ) ;
  19. //Проганяем циклом по всем принятым сообщениям
  20. for ( var i = 0 ; i obj. length ; i ++ ) <
  21. //Присваиваем переменной ID сообщения
  22. mid = obj [ i ] . id ;
  23. //Добавляем в чат сообщение
  24. $ ( “#msg-box ul” ) . append ( “
  25. ” + obj [ i ] . name + “: ” + obj [ i ] . msg + ” ” ) ;
  26. >
  27. //Прокручиваем чат до самого конца
  28. $ ( “#msg-box” ) . scrollTop ( 2000 ) ;
  29. >
  30. >
  31. > ) ;
  32. >
  33. //Первый запрос к серверу. Принимаем сообщения
  34. get_message_chat ( ) ;
  35. //Обновляем чат каждые две секунды
  36. $ ( “#t-box” ) . everyTime ( 2000 , ‘refresh’ , function ( ) <
  37. get_message_chat ( ) ;
  38. > ) ;
  39. //Событие отправки формы
  40. $ ( “#t-box” ) . submit ( function ( ) <
  41. //Запрашиваем имя у юзера.
  42. if ( $ ( “#t-box input[class=’name’]” ) . attr ( “value” ) == “” ) < alert ( «Пожалуйста, введите свое имя!» ) >else <
  43. //Добавляем в куки имя
  44. $. cookie ( “name” , $ ( “#t-box input[class=’name’]” ) . attr ( “value” ) ) ;
  45. //Тащим сообщение из формы
  46. var msg = $ ( “#t-box input[class=’msg’]” ) . val ( ) ;
  47. //Если сообщение не пустое
  48. if ( msg != “” ) <
  49. //Чистим форму
  50. $ ( “#t-box input[class=’msg’]” ) . attr ( “value” , “” ) ;
  51. //Генерируем Ajax запрос
  52. $. ajaxSetup ( < url : «chat.php» , type : «GET» , data : «event=set&name=» +
  53. $ ( “#t-box input[class=’name’]” ) . val ( ) + “&msg=” + msg > ) ;
  54. //Отправляем запрос
  55. $. ajax ( ) ;
  56. >
  57. >
  58. //Возвращаем false, чтобы форма не отправлялась.
  59. return false ;
  60. > ) ;
  61. > ) ;

Разберем этот скрипт…
Строка (3). Если в куках есть имя пользователя, то заполняем форму с именем. Для чего это сделано? Если пользователь обновил страничку с чатом или зашел заново на страницу с чатом, то ему не придется вводить свое имя заново.
Строка (7). Функция обновления чата. Чат обновляется не полностью, а присылаются только те сообщения, которых нет в чате.
Строка (9). Генерируем Ajax запрос. Для чего нужно отправлять лишнюю переменную «t=»+(new Date).getTime()? Если не отправить, то некоторые браузеры кэшируют одинаковые Ajax запросы. А нам это не нужно! т.к. не смогут обновляться сообщения. Функция (new Date).getTime() возвращает время в миллисекундах. Таким образом, браузер не кэширует запрос, т.к. при каждой отправке, генерируется разная строка.
Строка (16). Почему именно больше двух символов? Да потому что если все сообщения в чате есть, то сервер присылает не пустую строку, а “[]”. т.к. ответ генерируется в JSON.
Строка (37). Запрос новых сообщений раз в две секунды. Мне очень понравился плагин jQuery Timers. С помощью него можно очень гибко сделать повторение определенных действий любое количество раз.

В общем-то, и всё. Вот и готов наш чат. Проверку имени на валидность и смайлы оставляю для домашнего задания.

Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.

Источник статьи: http://habr.com/ru/sandbox/21047/

Создаем чат для сайта: HTML, JS, PHP и AJAX

Когда обычных комментариев становится недостаточно, приходит время создать чат.

С помощью чата пользователи общаются друг с другом, повышая интерес к сайту. Это важный элемент для вебинарных площадок, порталов со службой поддержки и страниц, где необходимо более живое, нефорумное общение. Гайд поможет на практике скомбинировать знания по HTML, JS, PHP и AJAX и создать готовый продукт.

Если знаний ещё недостаточно, обратите внимание на курс «Веб-разработчик c нуля до PRO».

Пишет о программировании, в свободное время создает игры. Мечтает открыть свою студию и выпускать ламповые RPG.

Каким должен быть чат

Удобство для пользователей превыше всего. Позаботьтесь, чтобы чат соответствовал современным требованиям:

  • сообщения отображаются корректно на всех устройствах;
  • их загрузка и отправка происходят без обновления страницы;
  • есть дополнительный контент — изображения, аудиосообщения, смайлики, стикеры и прочее.

Каркас чата на HTML

В первую очередь создаём форму отправки и контейнер для отображения сообщений:

Задаём стили

В первую очередь уделим внимание главным функциям чата, а после доработаем внешний вид.

Основная часть чата
на JS + PHP

Сообщения будут отправляться и загружаться с помощью AJAX. На JavaScript пишем функции работы с интерфейсом и связи с серверной частью, а на PHP — методы обработки полученных данных и взаимодействия с базой данных.

Создаем переменные на JS

Создаем функцию для запросов

Она получает переменную act, в которой хранится одно из трёх значений: auth (авторизация), load (загрузка) и send (отправка). От них зависит, какая информация будет передана в PHP-файл.

Создаём функцию обновления чата

И укажем для нашей функции интервал выполнения:

После отлавливается событие отправки формы — это поможет отказаться от обновления страницы:

Теперь займёмся самим обработчиком. В первую очередь с помощью функции session_start () запускается сессия, затем подключается база данных:

Создаём функцию авторизации

Создаём функцию загрузки

Создаём функцию отправки сообщений

В функции уже присутствует несложная валидация, но можно добавить и другие меры защиты от инъекций и спама:

  • проверку на дублирование прошлого сообщения;
  • удаление внешних ссылок;
  • цензуру мата;
  • премодерацию сообщений у некоторых групп пользователей и так далее.

Теперь, когда все функции готовы, пропишем их вызов.

Вызываем функции

Со стороны фронтенда мы ещё не реализовали авторизацию, но уже можем проверить чат, потому что в самом начале данные администратора были занесены в сессию. Вот как это выглядит:

Теперь, когда чат работает, пора добавить авторизацию. Для этого можно создать отдельную форму во фронте, но можно обойтись и модальными окнами. В функции send_request () дополним отправку запроса:

Дополнительные функции

Минимальные возможности чата у нас есть, и продукт можно запускать в релиз, но добавим ещё несколько полезных штук.

Смайлики

Создадим свой набор смайликов чата. Работать это будет так:

  • пользователь открывает специальное окошко и кликает по смайлику;
  • в поле ввода добавляется код смайлика (например, : sad: или: crazy:);
  • при выводе сообщения код смайлика заменяется на изображение.

Для начала добавим контейнер со смайликами и кнопку для его открытия:

Добавим скрипт для загрузки смайликов и открытия меню с ними:

А теперь и функцию добавления смайлика в поле:

После этого укажем, когда вызываются функции:

Приступим к загрузке смайликов и их преобразованию на PHP:

Эта функция сканирует папку со смайликами, а потом проверяет расширение файлов. Она очень удобна, потому что отображает в формате PNG все смайлики, которые мы добавили.

Чтобы вызвать её, добавим ещё один case в функцию switch () в конце обработчика:

Теперь с помощью регулярных выражений можно заменять код смайлика на изображение:

Вызывается эта функция при загрузке сообщений:

Ответ на сообщения

Чтобы добавить возможность отвечать кому-то конкретному, изменим функцию addEmoji (). При нажатии на ник собеседника будет меняться текст в поле ввода.

Для этого в load () изменим формат сообщений, добавив span к нику:

Заключение

Одной статьи недостаточно, чтобы охватить все возможности PHP и JS для разработки чатов. С помощью этих языков легко добавить:

  • ответ на конкретные сообщения;
  • форматирование текста;
  • отправку аудио;
  • разные «комнаты»;
  • чат-бота и многое другое.

Научиться делать подобные вещи самому не просто. Придётся перерыть гору литературы или искать готовые решения. На нашем курсе вы получите практические знания, которые помогут разобраться во всех деталях и делать более сложные проекты.

Веб-разработчик c нуля до PRO

Практический курс для тех, кто хочет стать профессиональным
веб-разработчиком, запустить свой интернет-проект или веб-сервис и получить первые заказы на разработку. Помимо просмотра уроков, вы будете делать реальные проекты, которые оценят. Ведь работодатели будут встречать вас в том числе и по тому, что увидят на аккаунте вашего GitHub. После прохождения обучения — гарантированное трудоустройство

Источник статьи: http://skillbox.ru/media/code/chat_dlya_sayta_html_js_php_i_nemnogo_ajax/

Как сделать чат

Как сделать чат

Думаю, что каждый из Вас знает, что такое чат. И очень часто на сайтах можно встретить либо маленькие чаты, либо достаточно большие и сложные. В этой статье я опишу принцип создания чата. Обратите внимание, что в этой статье не будет готового кода «скопировал-вставил«, а только алгоритм, с помощью которого Вы, обладая необходимыми знаниями, сможете сделать чат.

Ключевая особенность чата в том, что его содержимое обновляется автоматически. Отсюда и возникают все трудности.

Для начала разберём с Вами структуру таблицы в базе данных. Вот те поля, которые обязательно потребуются:

  • id — уникальный идентификатор.
  • name — имя, оставившего сообщение. Здесь также может быть, например, user_id, означающий id пользователя из другой таблицы.
  • message — сам текст сообщения.
  • date — дата отправления сообщения.

Безусловно, это только пример. Вы можете добавлять ещё массу других полей, тем самым, расширяя возможности Вашего чата.

Теперь необходимо вывести HTML-код:

<div id="chat">
  <table>
    <tr>
      <td>Имя</td>
      <td>Сообщение</td>
      <td>Дата</td>
    </tr>
    <tr>
      <td>Имя</td>
      <td>Сообщение</td>
      <td>Дата</td>
    </tr>
  </table>
</div>
<p>
  <input type="text" name="message" id="message" />
  <input type="button" value="Отправить" onclick="send()" />
</p>

В данном коде опять же всё как пример. Можно всё смело менять, но принцип должен быть тем же: есть место, где выводятся сообщения, причём они выводятся в одинаковом виде. Вместе с полем, где выводятся сообщения, есть текстовое поле и кнопка «Отправить«.

Обязательно для блока chat поставьте фиксированную высоту, чтобы при добавлении новых сообщений, у Вас этот блок не вырастал, также поставьте полосу прокрутки у него, чтобы можно было просмотреть все сообщения. Всё это делается с помощью CSS.

Теперь займёмся JavaScript:

<script type="text/javascript">
  function send() {
    var message = document.getElementById("message").value;
    var name = "Гость";
    /* Здесь блок отправки POST-запроса с данными (например, через Ajax) */
  }
  function update() {
    /* Здесь отправка запроса на получение всех сообщений (например, через Ajax) */
    /* Здесь вывод сообщений в определённом формате прямо в HTML-код с использованием DOM, либо JQuery. */
  }
  setInterval("update()", 1000); // Обновление окна чата каждую секунду
</script>

И, наконец, PHP-код (добавление новых сообщений):

<?php
  /* Получаем данные, полученные из JavaScript */
  $message = $_POST["message"];
  $name = $_POST["name"];
  $date = date(); // Узнаём текущее время и дату
  /* Здесь добавляем в таблицу новую запись */
?>

И последний файл, которые потребуется — это получение всех сообщений из таблицы:

<?php
  /* Вытаскиваем все записи из таблицы */
  /* Получаем двумерный массив из полученных данных */
  /* Преобразуем массив в json-формат и возвращаем его в javascript, где он уже будет выводиться */
?>

Всё, круг замкнулся, и чат заработал. Как видите, сделать чат достаточно сложно и нужно обладать большим багажом знаний. Но я надеюсь, что данная статья здорово облегчит Вам эту задачу. Абсолютно любой чат, какой бы он сложный ни был, основан на принципах, описанных в данной статье, поэтому смело можете его использовать как каркас.

  • Создано 16.04.2012 13:59:17


  • Михаил Русаков

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Понравилась статья? Поделить с друзьями:
  • Как написать чат бота для telegram на javascript
  • Как написать чат бот телеграм
  • Как написать чат бот на нейросети
  • Как написать часы на питоне
  • Как написать часы на python