Сен
Простой чат на AJAX
Начал замечать на многих сайтах наличие, либо окошка чата или окошка онлайн консультанта. Не секрет что яндекс относит наличие на сайте чата или консультанта к положительным коммерческим факторам. Всвязи с этим я попытался наваять ajax чат для сайта.
И так поехали писать чат на ajax php. Создаём файл chat.js
, а так же сразу создадим файлы add.php
и get_json.php
, но о них позже .
Создаём файл chat.php
. Подключаем к нему jquery и chat.js
. Создаём в файле chat.php
поле с именем участника чата и поле с сообщением в чат, а так же кнопку с id btnSend
для отправки сообщения. На кнопку с id btnSend
в файле chat.js повешен обработчик событий клик. В див с id chat
будут выводиться наши чат сообщения.
Ниже показан листинг куска кода из файла chat.php
. Не обращайте
внимания на непонятные css классы, это классы из bootstrap.
<div id="chat"></div> <form class="form-horizontal" role="form"> <div class="form-group"> <label for="name" class="col-sm-3 col-sm-offset-1 control-label">Ваше имя для чата</label> <div class="col-sm-4 "> <input type="text" class="form-control" id="name" placeholder="Введите ваше имя" name="name"/> </div> </div> </form> <form class="form-horizontal" role="form"> <div class="form-group"> <label for="text" class="col-sm-3 col-sm-offset-1 control-label">Ваше сообщение</label> <div class="col-sm-7 "> <textarea class="form-control" rows="3" id="text" placeholder="Введите ваш сообщение" name="text"></textarea> </div> </div> </form> <div class="col-sm-offset-4 col-sm-4 col-xs-offset-2 col-xs-7"> <button id="btnSend" class="submit btn btn-primary col-sm-12 col-xs-12 btn-lg">Отправить сообщение</button> </div>
В chat.js
обрабатывем данные из полей ввода и методом post в формате json отправляем данные в add.php
. Кусок кода из chat.js
ниже.
$('#btnSend').click(function(elem){ //при клике получаем сообщения из полей с ид name и text var name = $('#name').val(); var text = $('#text').val(); //и методом POST в формате json отправляем их в add.php $.post('add.php', {name: name, text: text}, function(){ //поле text стираем(тоесть делаем пустым '') $('#text').attr('value', ''); }); });
В файле add.php
мы получаем данные. Конечно их надо бы проверить после получения но это
мы пока опустим. Добавляем к данным дату и
записываем их в файл messages.txt
в одну строчку с уникальным разделителем "_". Так же для того что бы файл не разросся до больших размеров,
сделана защита от переполнения. При достижении в файле messages.txt
строк сообщений более 100, все строки стираются кроме последних пяти.
Они зписываются заново. Ниже листинг add.php
.
<?php $name = $_POST['name'];//получили данные $text = $_POST['text']; if(($name != '') && ($text != '')){ $strings = file('messages.txt'); //если строк в файле messages.txt > 100 if(count($strings)>100){ //получаем все строки из файла в виде нумерованного массива $textarr=file('messages.txt'); $arr=array_slice($textarr, -5); //переписываем данные в файл записываем только //последние 5 строк массива $f = fopen('messages.txt', 'w+'); //в цикле записываем данные в файл, //каждое значение массива на новой строке в файле foreach($arr as $ar){ $f = fopen('messages.txt', 'a+');//открыли файл fwrite($f, $ar);//запись fclose($f);//закрыли файл } } $f = fopen('messages.txt', 'a+');//открыли файл fwrite($f, date('Y-m-d H:i:s') . "___");//запись fwrite($f, $name . "___");//запись в файл fwrite($f, $text . "\n");//запись и добавили конец строки fclose($f);//закрыли файл } ?>
Всё, наши все сообщения пишутся в файл. Теперь нам нужно сделать так, что бы эти сообщения выводились на экран.
Для этого напишем в файле chat.js
функцию chatRequest()
. Эта функция обращается к файлу get_json.php
и передаёт
ему параметр __maxId
. Параметр _maxId
указывает сколько сообщений у нас есть на данный момент. По умолчанию в начале стоит 0.
Соответственно для начала __maxId
определяем как глобальную переменную.
function chatRequest(){ // Отправка запроса методом POST. $.post('get_json.php', {maxId: _maxId}, chatResult, 'json'); }
Так же в функции chatRequest()
определено, что при удачном выполнении запроса данные ответа возвращаются в формате json
и вызывается функция chatResult
из файла chat.js
. Но давайте сначала разберём файл get_json.php
.
Файл get_json.php
принимает данные, вычисляет строку, которая была не отображена на экране, делает из неё массив, упаковывает в формат json и
отправляет в функцию chatResult(msgs)
.
<?php $maxId = $_POST['maxId']; $strings = file('messages.txt'); $messages = array(); //если maxId меньше кол-ва строк в файле(count($strings)), // то мы прибавляем +1 к i , for($i = $maxId; $i < count($strings); $i++) { //берём строку с номером i разбиваем её по уникальному разделителю //'___' и делаем из неё именованные элементы массива $string = explode('___', $strings[$i]); $arr['date'] = $string[0]; $arr['name'] = $string[1]; $arr['text'] = $string[2]; //упаковываем всё в массив messages[] $messages[] = $arr; } //переводим массив в json и отправляем echo json_encode($messages); ?>
ChatResult
дописывает данные полученой строки в массив _messages
. Мы его объявили в самом начале файла и сделали его массивом.
И потом функция заново выводит все написанные сообщения в цикле из массива _messages
в див с id #chat
. Сделал так, что бы
выводилось только пять последних сообщений. Для чётного и нечётного сообщения выводится своя вёрстка. Для вёрстки я опять же
использую бутстрап. Листинг функции ChatResult
.
function chatResult(msgs){ // Добавление новых сообщений в массив. for(var i = 0; i < msgs.length; i++) { var m = new Object(); m.dt = msgs[i]['date']; m.name = msgs[i]['name']; m.text = msgs[i]['text']; _messages.push(m); _maxId++; } // Вывод массива сообщений. var html = ''; //пока сообщений в фаиле меньше 5 if(_messages.length<=5){ for (var i = _messages.length - 1; i >=0; i--) { var m = _messages[i]; //проверка что сообщение чётное if (i%2==1){ //вёрстка html +='<div class="qbox clearfix"><div class="bname col-md-2 pull-left center-block"><p>'+m.name+'</p></div>'; html +='<div class="bnameprobel col-md-10 pull-left"></div><div class="clearfix"></div><div class="col-md-2 pull-left"><img src="/iconman.png" class="img-responsive col-md-10 col-md-push-1" alt=""></div>'; html +='<div class="bnameprobel col-md-10 pull-left"><blockquote class="post bg-success pull-left"><p >'+m.text+'<span class="data">'+m.dt+'</span></p></blockquote></div></div>'; }else{ //вёрстка html +='<div class="qbox clearfix"><div class="bname col-md-2 pull-right center-block"><p>'+m.name+'</p></div>'; html +='<div class="bnameprobel col-md-10 pull-right"></div><div class="clearfix"></div><div class=" col-md-2 pull-right"><img src="/iconman.png" class="img-responsive col-md-10 col-md-push-1" alt=""></div>'; html +='<div class="bnameprobel col-md-10 pull-right"><blockquote class="post bg-info pull-right"><p >'+m.text+'<span class="data">'+m.dt+'</span></p></blockquote></div></div>'; } } //сообщений в фаиле больше 5 }else{ for (var i = _messages.length - 1; i >= _messages.length-5; i--){ var m = _messages[i]; //проверка что сообщение чётное if (i%2==1){ //вёрстка html +='<div class="qbox clearfix"><div class="bname col-md-2 pull-left center-block"><p>'+m.name+'</p></div>'; html +='<div class="bnameprobel col-md-10 pull-left"></div><div class="clearfix"></div><div class="col-md-2 pull-left"><img src="/iconman.png" class="img-responsive col-md-10 col-md-push-1" alt=""></div>'; html +='<div class="bnameprobel col-md-10 pull-left"><blockquote class="post bg-success pull-left"><p >'+m.text+'<span class="data">'+m.dt+'</span></p></blockquote></div></div>'; }else{ //вёрстка html +='<div class="qbox clearfix"><div class="bname col-md-2 pull-right center-block"><p>'+m.name+'</p></div>'; html +='<div class="bnameprobel col-md-10 pull-right"></div><div class="clearfix"></div><div class=" col-md-2 pull-right"><img src="/iconman.png" class="img-responsive col-md-10 col-md-push-1" alt=""></div>'; html +='<div class="bnameprobel col-md-10 pull-right"><blockquote class="post bg-info pull-right"><p >'+m.text+'<span class="data">'+m.dt+'</span></p></blockquote></div></div>'; } } } //выводим все сообщения $('#chat').html(html); }
Для того что бы у нас чат постоянно обновлялся мы делаем постоянные запросы к функции chatRequest()
с периодичностью 2 сек.
// Запрашиваем сообщения каждые 2 секунды setInterval(chatRequest, 2000);
Ну вот мы и написали простой чат на ajax php для сайта. Для полноты картины покажем полный листинг файла chat.js
var _maxId; var _messages; $(document).ready(function(){ // Инициализация. _maxId = 0; _messages = []; chatRequest(); // Запрашиваем сообщения каждые 2 секунды setInterval(chatRequest, 2000); $('#btnSend').click(function(elem){ //при клике получаем сообщения из полей с ид name и text var name = $('#name').val(); var text = $('#text').val(); //и методом POST в формате json отправляем их в add.php $.post('add.php', {name: name, text: text}, function(){ //поле text стираем(тоесть делаем пустым '') $('#text').attr('value', ''); }); }); }); function chatRequest() { // Отправка запроса методом POST. $.post('get_json.php', {maxId: _maxId}, chatResult, 'json'); } function chatResult(msgs){ // Добавление новых сообщений в массив. for(var i = 0; i < msgs.length; i++) { var m = new Object(); m.dt = msgs[i]['date']; m.name = msgs[i]['name']; m.text = msgs[i]['text']; _messages.push(m); _maxId++; } // Вывод массива сообщений. var html = ''; //пока сообщений в фаиле меньше 5 if(_messages.length<=5){ for (var i = _messages.length - 1; i >=0; i--) { var m = _messages[i]; //проверка что сообщение чётное if (i%2==1){ //вёрстка html +='<div class="qbox clearfix"><div class="bname col-md-2 pull-left center-block"><p>'+m.name+'</p></div>'; html +='<div class="bnameprobel col-md-10 pull-left"></div><div class="clearfix"></div><div class="col-md-2 pull-left"><img src="/iconman.png" class="img-responsive col-md-10 col-md-push-1" alt=""></div>'; html +='<div class="bnameprobel col-md-10 pull-left"><blockquote class="post bg-success pull-left"><p >'+m.text+'<span class="data">'+m.dt+'</span></p></blockquote></div></div>'; }else{ //вёрстка html +='<div class="qbox clearfix"><div class="bname col-md-2 pull-right center-block"><p>'+m.name+'</p></div>'; html +='<div class="bnameprobel col-md-10 pull-right"></div><div class="clearfix"></div><div class=" col-md-2 pull-right"><img src="/iconman.png" class="img-responsive col-md-10 col-md-push-1" alt=""></div>'; html +='<div class="bnameprobel col-md-10 pull-right"><blockquote class="post bg-info pull-right"><p >'+m.text+'<span class="data">'+m.dt+'</span></p></blockquote></div></div>'; } } //сообщений в фаиле больше 5 }else{ for (var i = _messages.length - 1; i >= _messages.length-5; i--){ var m = _messages[i]; //проверка что сообщение чётное if (i%2==1){ //вёрстка html +='<div class="qbox clearfix"><div class="bname col-md-2 pull-left center-block"><p>'+m.name+'</p></div>'; html +='<div class="bnameprobel col-md-10 pull-left"></div><div class="clearfix"></div><div class="col-md-2 pull-left"><img src="/iconman.png" class="img-responsive col-md-10 col-md-push-1" alt=""></div>'; html +='<div class="bnameprobel col-md-10 pull-left"><blockquote class="post bg-success pull-left"><p >'+m.text+'<span class="data">'+m.dt+'</span></p></blockquote></div></div>'; }else{ //вёрстка html +='<div class="qbox clearfix"><div class="bname col-md-2 pull-right center-block"><p>'+m.name+'</p></div>'; html +='<div class="bnameprobel col-md-10 pull-right"></div><div class="clearfix"></div><div class=" col-md-2 pull-right"><img src="/iconman.png" class="img-responsive col-md-10 col-md-push-1" alt=""></div>'; html +='<div class="bnameprobel col-md-10 pull-right"><blockquote class="post bg-info pull-right"><p >'+m.text+'<span class="data">'+m.dt+'</span></p></blockquote></div></div>'; } } } //выводим все сообщения $('#chat').html(html); }
update 5.10.16
Заткнул простейшую дыру от простейшей XSS атаки. Все просто задолбали ломать чат)). Было лень фильтровать входящие данные, но пришлось переделать. Функция для фильтрации.
/*ф-я фильтрации*/ function myclear($dt){ $dt=stripslashes($dt); $dt=strip_tags($dt); $dt=trim($dt); return $dt; }
теперь файл add.php выглядит так
/*ф-я фильтрации*/ function myclear($dt){ $dt=stripslashes($dt); $dt=strip_tags($dt); $dt=trim($dt); return $dt; } $name = myclear($_POST['name']);//фильтруем $text = myclear($_POST['text']); //было раньше //$name = $_POST['name']; //$text = $_POST['text']; if(($name != '') && ($text != '')){ $strings = file('messages.txt'); if(count($strings)>100){ //получаем все строки из файла в виде нумерованного массива $textarr=file('messages.txt'); $arr=array_slice($textarr, -5); //переписываем данные в файл записываем только последние 3 строки массива $f = fopen('messages.txt', 'w+'); //в цикле записываем данные в файл, каждое значение массива на новой строке в файле foreach($arr as $ar){ $f = fopen('messages.txt', 'a+');//открыли файл fwrite($f, $ar);//запись fclose($f);//закрыли файл } } $f = fopen('messages.txt', 'a+');//открыли файл fwrite($f, date('Y-m-d H:i:s') . "___");//запись fwrite($f, $name . "___");//запись в файл fwrite($f, $text . "\n");//запись и добавили конец строки fclose($f);//закрыли файл }
Комментарии
admin776
09.01.2017 22:34 Ответить
Спасибо большое, то что нужно!
петр
15.06.2017 17:53 Ответить
а как сделать проверку например на плохие слова
Алексей Григорьев
17.06.2017 06:41 Ответить
Если честно, таким вопросом ещё не занимался. Но думаю можно что нибудь сделать используя регулярные выражения
Toxa
12.03.2018 01:42 Ответить
Я думаю, что нужно создать файл или даже просто создать переменную туда вписать все плохие слова и сделать проверку типа, если $_POST['message '] содержит такое слово(плохое) то заменить это слово на *****, регуляркой
Алексей Григорьев
12.03.2018 21:11 Ответить
Да, кстати отличный вариант, и реализовать не сложно. Список стоп слов можно и в инете найти
Дмитрий
07.10.2017 17:33 Ответить
А как сделать что бы сообщения выводились снизу а не сверху ?
Дмитрий
07.10.2017 17:34 Ответить
И сделать очистку формы после отправки
Алексей Григорьев
07.10.2017 21:07 Ответить
Что бы сообщения выводились после формы отправки в файле chat.php перенесите div с id="chat" под форму отправки. Как очистить форму чата пока не думал, после отправки сообщения можно попробовать перезапрашивать страницу силами js или php, но надо подумать получше, сейчас времени нет пока на это.