Nickolay.info. PHP. Простой чат на JQuery

Мы хотим написать очень простой чат, которому для работы достаточно нескольких килобайт кода и одного файла с данными. Сначала сформулируем требования.

Чего в нашем чате не будет точно:

Тем не менее, вот что нужно даже самому простому чату, как мне кажется:

Всё это нам обеспечит библиотека JQuery, так что необходимости изобретать велосипед нет.

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

Скачав JQuery (не обязательно самый новый, хватит и версии 1.3) положим его в папку чата под именем jquery.js.

Все наши файлы будем сохранять в Юникоде (UTF-8) без BOM, это важно, иначе рискуем получить трудноуловимые ошибки.

Пример такой ошибки -
session_start() [function.session-start]: Cannot send session cache limiter - headers already sent
вылезающей, даже если оператор session_start() стоит первым в файле.
А всё банально - файл Юникода с BOM, например, отредактированный Блокнотом Вындоус

Так что для редактирования нам подойдёт Notepad++ (меню Кодировки - Преобразовать в UTF-8 без BOM) ну или встроенный текстовый редактор из Far Manager 2, а вот Блокнот Windows, лепящий BOM куда ни попадя, не подойдёт.

Стиль традиционно будет называться style.css, в общем-то, всё равно, что там, но все размеры для простоты укажем в пикселах, а окно чата (раздел div с именем chatbox) опишем так, чтобы при необходимости обеспечивалась вертикальная прокрутка внутри раздела:

#chatbox {  
 height:400px;  
 width:700px;  
 overflow-x:auto;
 overflow-y:scroll;
}

Все сообщения файла будут "лежать" в файле log.html, пока что он пуст и имеет размер 0 байт. Файл functions.php будет содержать обычные функции для удаления лишних пробелов и борьбы с кавычками, а также метод add_in_file для записи в чат нового сообщения, вызов функции session_start - так как мы собираемся хранить имя пользователя в его сессии, и код, исполняемый один раз при старте системы.

Вот реализация add_in_file, по правде говоря, ей недостаёт безопасности при работе с "плоским" файлом чата.

function add_in_file ($newstr) {
  define ("LOGSIZE","100");
  $msgs = file ("log.html");
  if ($msgs===false) die ("Нет файла лога, обратитесь к администратору");
  else {
   if (count($msgs)>0 and $newstr==$msgs[count($msgs)-1]);
   else if (count($msgs)>=LOGSIZE) {
    $msgs=array_slice ($msgs,-(LOGSIZE-1));
    array_push ($msgs, $newstr);
    $i=file_put_contents ("log.html",$msgs);
    if (!$i) die ("Не могу записать файл лога, обратитесь к администратору");
   }
   else {
    $fp = fopen("log.html", 'a');
    fwrite($fp, $newstr);
    fclose($fp);  
   }
  }
}

Тем не менее, примитивная защита от флуда тут есть, новая строка сравнивается с последней из лога. Так как строки лежат в файле уже с меткой времени вида ЧЧ:ММ (это будет видно ниже), то флудить будет таки можно - но только разок в минуту :)

Файл index.php - это весь наш чат. В нём будут следующие разделы:

Всё вместе выглядит так:

<?php
 if(isset($_POST['name'])){ //Если пользователь вошел в чат 
  if (trimall($_POST['name'])!='') {
   $_SESSION['name']=magic(htmlspecialchars(trimall($_POST['name'])));
   add_in_file ("<div class='msgln'><sup>(".date("H:i").")</sup> <i>Пользователь ".
    $_SESSION['name']." вошёл в чат</i><br></div>\n");
  }  
  else {
   echo '<span class="error">Пожалуйста, введите непустое имя</span>';  
  }  
 }
 if(!isset($_SESSION['name'])) { //Если не вошли в чат - форма для входа
  echo'
  <div id="loginform">
  <form action="index.php" method="post"> 
   <p>Введите имя, под которым хотите войти:</p> 
   <label for="name">Имя:</label> 
   <input type="text" name="name" id="name" maxlength="32"/> 
   <input type="submit" name="enter" id="enter" value="Войти!" /> 
  </form> 
  </div>';
 }  
 else { //Иначе - элементы чата
?>  
 <div id="wrapper">  
  <div id="menu">  
   <p class="welcome">Вы вошли как <b><?php echo $_SESSION['name']; ?></b></p>  
   <p class="logout" align="right"><a id="exit" href="#">Выйти</a></p>  
   <div style="clear:both"></div>
  </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>  
  <form name="message" id="message" action="" method="post">
   <input name="usermsg" type="text" id="usermsg" size="63" maxlength="1024" />  
   <input name="submitmsg" type="submit"  id="submitmsg" value="Сказать" />
  </form>  
 </div>  
<?php  
 }  
?>

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

<script type="text/javascript">  
 //Собственно чат
 $(document).ready(function() {
  $("#exit").click(function() { //Если пользователь хочет выйти
   if (confirm("Выйти из чата?")==true) { window.location = 'index.php?logout=true'; }
  });
  $('#message').submit(function(e) { //Если пользователь отправил сообщение  
   var clientmsg = $("#usermsg").val();
   $.post("post.php", {text: clientmsg});
   $("#usermsg").attr("value", "");  
   return false;  
  });
  function loadLog() { //Загрузить лог чата
   var oldscrollHeight = $("#chatbox").attr("scrollHeight") - 20; 
   $.ajax ({
    url: "log.html",  
    cache: false,
    success: function(html) {
     $("#chatbox").html(html); //Автопрокрутка
     var newscrollHeight = $("#chatbox").attr("scrollHeight") - 20;
     if (newscrollHeight > oldscrollHeight) {  
      $("#chatbox").animate({ scrollTop: newscrollHeight }, 'normal');
     }                 
    }  
   });  
  }
  //Обновление каждые 2.5с
  setInterval (loadLog, 2500);
 });
</script>

Здесь тоже есть пара нюансов, например, если написать

  $("#submitmsg").click(function()

вместо

  $('#message').submit(function(e)

(как часто и делают), то форма не будет отправляться в IE по нажатию Enter, кстати, если не указать атрибут id="message" в теге <form>, а только name="message", скорей всего, тоже не будет. IE "строже" относится к DOM, чем альтернативные браузеры.

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

<?php
 require_once ("functions.php");
 if (isset($_GET['logout'])) { //Если пользователь покинул чат 
  add_in_file ("<div class='msgln'><sup>(".date("H:i").")</sup> <i>Пользователь ".
   $_SESSION['name']." покинул чат</i><br></div>\n");
  session_destroy();  
  header("Location: index.php");
 }
?>

Потом уже выведем заголовок HTML-документа и подключим скрипты.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Simple JQuery Chat</title>
<link type="text/css" rel="stylesheet" href="style.css"/>
<script type="text/javascript">
 function copyNick (name) {
  document.message.usermsg.value+=name+', ';
  document.message.usermsg.focus();
 }
</script>
<script type="text/javascript" src="jquery.js"></script>
</head>
<body>

Маленький скрипт copyNick, думаю, не нуждается в JQuery - он просто будет копировать ник, по которому мы щёлкнули, в строку ввода сообщения.

Остаётся дописать в конце

</body></html>

и обратить внимание, что самая суть чата - вызов из яваскрипта файла post.php, который отвечает за добавление очередного сообщения:

<?php
 require_once ("functions.php");
 if (isset($_SESSION['name'])) {
  add_in_file ("<div class='msgln'><sup>(".date("H:i").")</sup> <b><a href=\"#\" onClick=\"copyNick('".
   $_SESSION['name']."')\">".$_SESSION['name']."</a></b>: ".magic(htmlspecialchars(trimall($_POST['text']))).
   "<br></div>\n");
 }  
?>

Собственно, это всё, осталось посмотреть, что получилось.

 Чат в работе

Никаких особенных настроек прав мне не потребовалось, просто скопировал файлы на хостинг, права на файл log.html остались 644. Проверил в текущих версиях Firefox, Opera, Chrome, Internet Explorer 6-7-8 и встроенном браузере на коммуникаторе под Android 2.2.2, вроде бы, работает, и глюков не выявлено. Для работы чата, разумеется, нужен включённый JavaScript, в браузерах, альтернативных ИЕ, работа сессий предполагает также, что включена настройка "Разрешить cookie".

 Скачать исходники Simple JQuery Chat в архиве ZIP (23 Кб)

Файлы в архиве могут несколько меняться по отношению к тексту статьи, например, если "всплывут" какие-то исправления или дополнения.

Рейтинг@Mail.ru

вверх гостевая; E-mail