2016
26
Сен

Простой чат на AJAX

grigoriev
7773
chat ajax
скачать парсер php
DOWNLOAD
посмотреть парсер php
DEMO

Начал замечать на многих сайтах наличие, либо окошка чата или окошка онлайн консультанта. Не секрет что яндекс относит наличие на сайте чата или консультанта к положительным коммерческим факторам. Всвязи с этим я попытался наваять 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

admin776

09.01.2017 22:34 Ответить

Спасибо большое, то что нужно!

петр

петр

15.06.2017 17:53 Ответить

а как сделать проверку например на плохие слова

Алексей Григорьев

Алексей Григорьев

17.06.2017 06:41 Ответить

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

Добавить комментарий


Защитный код
Обновить