Generated with Avocode. Generated with Avocode. Generated with Avocode. Group 15 close hat Generated with Avocode. Generated with Avocode. Generated with Avocode. Generated with Avocode. Generated with Avocode. Generated with Avocode. path40

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

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

С помощью чата пользователи могут общаться друг с другом. Иногда он становится самой популярной частью сайта, если аудитория заинтересована в общении, а качество реализации чата не заставляет плакать.

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

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

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

Каркас чата на 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%;

}

Отображаться этот чат будет так:

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

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

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

Начать стоит с создания переменных на JS:

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=':".$ext[0].":' 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 для разработки чатов. Также можно добавить:

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

Научиться делать подобные вещи можно на курсе «PHP-разработчик». Там вы получите практические знания, которые позволят делать более сложные проекты.

Курс «PHP-разработчик»
Обширная программа для изучения PHP, состоящая из 4 курсов. Поможет с нуля овладеть популярным языком программирования, устроиться в IT-компанию вашей мечты или стать независимым разработчиком.
  • Живая обратная связь с преподавателями
  • Неограниченный доступ к материалам курса
  • Стажировка в компаниях-партнёрах
  • Дипломный проект от реального заказчика
  • Гарантия трудоустройства в компании-партнёры для выпускников, защитивших дипломные работы
Хочешь получать крутые статьи по программированию?
Подпишись на рассылку Skillbox
Посмотреть