Суббота, 23 Ноября 2024, 09:52

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Урок по созданию чата на jQuery (php+mysql)
AssasinДата: Среда, 28 Сентября 2011, 18:44 | Сообщение # 1
web-coder
Сейчас нет на сайте
Доброго времени суток. Недавно меня в скайпе попросили сделать чат без перезагрузки страницы. Я принципиально отказался, т.к. у человека есть свободное время и если он захочет, то может сам найти инфу и написать такой чат. Но вот что бы такие вопросы не возникали в дальнейшем я решил написать небольшой урок по созданию чата с использованием библиотеки jQuery.
Вот такой чат получится в конечном итоге:

Подготовка
Нам понадобятся такие сторонние файлы:
- jquery (скачать) вся клиентская логика будет написана на нем
- apprise (скачать) для украшения всплывающих окошек
Все создаваемые файлы сохранять в кодировке utf-8 без BOM, т.к. json другие кодировки не любит.
Настройка сайта
Создадим файл .htaccess и впишем в него:
Code
# Главный файл
DirectoryIndex index.html

# Кодировка страниц
AddDefaultCharset UTF-8

Клиентская часть
Создаем папку style и вставляем в нее скачаные файлы jquery.js, apprise.css, apprise.js. Также создаем в ней файлы style.css, script.js.
Открываем style.css и записываем каким будет выглядеть чат:
Code

/* Тело документа */
body {
  margin: 0 auto;
  padding: 0;
  width: 800px;
  background:rgba(0, 0, 0, 0.3);
}
/* Главный блок */
#stage {
  height: 290px;
  display: block;
}
/* Блок сообщений */
#message {
  display: block;
  float: left;
  width: 590px;
  height: 220px;
  overflow: auto;
  margin: 10px 0px 10px 10px;
}
/* Блок отображения юзверей */
#user {
  display: block;
  float: right;
  width: 180px;
  height: 220px;
  margin: 10px 10px 10px 0px;
}
/* Закругляем красиво углы */
.corner {
  background:#eee;
  border:1px solid #fff;
  box-shadow:0px 3px 7px #333;
  -moz-box-shadow:0px 3px 7px #333;
  -webkit-box-shadow:0px 3px 7px #333;
  -moz-border-radius:4px;
  -webkit-border-radius:4px;
  border-radius:4px;
  -khtml-border-radius:4px;
}
/* Отступ от границ */
.d {
  padding: 10px;
}
/* Блок отправки сообщения */
#send_line {
  margin: 0px 10px 10px 10px;
  width: 780px;
}
/* стиль input отправки сообщения */
.msg {
  width: 760px;
  margin: 4px 0px 4px 10px;
}

Далее открываем файлик script.js и пишем следующий код, он будет отвечать за логику на стороне клиента:
Code

$(document).ready(function(){/* Как только загрузится документ, начинает работать код, который расположен внутри */
  var name = null, // Будущее имя пользователя
   id = 0; // id последнего сообщения
  /* Начало работы, создаем запрос, который отсылает в скрипт core.php данные start=true методом POST ($_POST['start']=true) и принимаем от сервера данные в формате json */
  $.ajax({
   type: "POST",
   url: "core.php",
   data: "start=true",
   dataType: 'json',
   success: function(data) {
    /* Если пришла ошибка от сервера, то показываем её пользователю и перезагружаем страницу */
    if (data.err) {
     if (data.err == 2) {
      apprise('Невозможно найти БД', {}, function(r){
       location.href = "index.html";
      });
     } else if (data.err == 1) {
      apprise('База данных ушла в себя', {}, function(r){
       location.href = "index.html";
      });
     }
     return false;
    }
    /* Если ошибок нет и получен ответ = 0 то показываем пользователю всплывающее окно */
    if (data.ans == 0) {
     apprise('Введите логин', {'input': true}, function(login){ /* Если пользователь не ввел логин либо нажал "Отменить" перезагружаем страницу */
      if (login == false) {
       location.href = "index.html";
      } else {/* Если ввел логин, то отправляем в файл core.php введеный логин и принимаем ответ опять же в формате json */
       $.ajax({
        type: "POST",
        url: "core.php",
        data: "name="+login,
        dataType: 'json',
        success: function(data) {
         /* Если ответ = 0, то запоминаем имя пользователя и id последнего сообщения */
         if (data.ans == 0) {
          name = data.login;
          id = data.id;
         } else { /* Иначе выдаем ошибку и перезагружаем страницу */
          apprise('Такой логин уже используется', function(r){
                              location.href = "index.html";
          });
         }
        }
       });
      }
     });
    } else { /* Если получаем ответ != 0, то запоминаем имя пользователя и id последнего сообщения */
     name = data.login;
     id = data.id;
    }
   }
  });
  /* Функция которая возвращает сообщения и пользователей онлайн, обновляется каждые 2 сек (2000 милисек) */
  update();
  setInterval(update, "2000");
   
  function update() {
   /* Отправляем на сервер (файл core.php) данные update=1 и id последнего сообщения */
   $.ajax({
    type: "POST",
    url: "core.php",
    data: "update=1&id="+id,
    dataType: 'json',
    success: function(data) {
     /* Проверяем наличие ошибок */
     if (data.err) {
      if (data.err == 2) {
       apprise('Невозможно найти БД', {}, function(r){
        location.href = "index.html";
       });
      } else if (data.err == 1) {
       apprise('База данных ушла в себя', {}, function(r){
        location.href = "index.html";
       });
      }
      return false;
     }
     /* Обновляем список пользователей */
     if (data.user != $("#user .d").html()) {
      $("#user .d").html(data.user);
     }
     /* Добавляем новое сообщение на экран, прокручиваем скролл вниз и удаляем старые сообщения, оставивши последние 10 */
     if (data.msg != "") {
      id = data.id;
      $('#message .d').append(data.msg);
      $('#message').scrollTop($('#message')[0].scrollHeight);
      var size = $("#message .d div").size();
      if (size > 10) {
       for (var i = 0; i < size-10; i++) {
        $("#message .d div").eq(i).remove();
       }
      }
     }
    }
   });
   /* удаляем старые сообщения, оставивши последние 10. Данное действие дублируется, т.к. при загрузке страницы с чатом удаляются сообщения и при каждом новом полученом сообщении */
   var size = $("#message .d div").size();
   if (size > 10) {
    for (var i = 0; i < size-10; i++) {
     $("#message .d div").eq(i).remove();
    }
   }
  }
  /* Отслеживаем нажатие клавиш */
  $('.msg').keydown(function(event){
   if (event.which == 13) { /* Если нажато Enter, запоминаем сообщение и  */
    var msg = $(this).val(),
     then = $(this); /* Обращение на самого себя, т.е. на элемент, который имеет класс msg (в нашем случае это input) */
    if (msg == "") { /* Если сообщение пустое, то прекращаем выполнять следующий код*/
     return false;
    }
    /* Отправляем на сервер сообщение и если пришел положительный ответ (!= 0) то прокручиваем блок сообщений вниз и очищаем строку в которую вводим сообщение */
    $.ajax({
     type: "POST",
     url: "core.php",
     data: "msg="+msg,
     dataType: 'json',
     success: function(data) {
      if (data.ans != 0) {
       $('#message').scrollTop($('#message')[0].scrollHeight);
       then.val("");
      }
     }
    });
   };
  });
});

Ну и последнее это сам файл index.html, выходим с папки style и создаем его:
Code
<!DOCTYPE html>
<html>
     <head>
         <title>Чат на jQquery</title>
         <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
         <link rel="stylesheet" type="text/css" href="/style/style.css" />
   <script type="text/javascript" src="/style/jquery-1.6.2.min.js"></script>
   <script type="text/javascript" src="/style/apprise-1.5.full.js"></script>
   <link rel="stylesheet" href="/style/apprise.css" type="text/css" />
   <script type="text/javascript" src="/style/script.js"></script>
     </head>
     <body>
         <div id="stage">
    <div id="message" class="corner"><div class="d"></div></div>
    <div id="user" class="corner"><div class="d"></div></div>
    <div style="clear:both;"></div> <!-- Данный блок указывает что его обтекать нельзя, поэтому следующие данные будут отображаться ниже, а не где то сбоку. Своеобразный <br> только для блоков (div)  -->
    <div id="send_line" class="corner">
     <input type="text" class="msg" maxlength="500">
    </div>
   </div>
     </body>
</html>

С клиентом разобрались, теперь приступаем к серверной стороне.
Серверная часть
В той же папке где и файл index.html создаем файл core.php
Code
<?php
session_start();
/* Данные для подключения к БД */
define("DB_HOST", "localhost");
define("DB_USER", "root");
define("DB_PASS", "");
define("DB_NAME", "chat");
/* Фильтрация всех получаемых переменных */
$start = htmlspecialchars(stripslashes($_POST['start']));
$name = htmlspecialchars(stripslashes($_POST['name']));
$msg = htmlspecialchars(stripslashes($_POST['msg']));
$update = htmlspecialchars(stripslashes($_POST['update']));
$id = htmlspecialchars(stripslashes($_POST['id']));
/* Соединение с БД и если не удачное, то отправка ошибок клиенту */
$connect = mysql_connect(DB_HOST, DB_USER, DB_PASS);
if (!$connect) {
  $data['err'] = 1;
  echo json_encode($data);
  exit;
}
$db_sel = mysql_select_db(DB_NAME,$connect);
if (!$db_sel) {
  $data['err'] = 2;
  echo json_encode($data);
  exit;
}
# Установка языка записи в БД
mysql_query("SET NAMES utf8");
/* Если игрок загрузил страницу чата, то наш script.js передает серверу данные $_POST['start'] вот и обрабатываем эти данные */
if (!empty($start)) {
  /* Если не существует сессия name, то возвращаем 0, в другом случае указываем логин игрока, который хранится в сессии, передаем id последнего сообщения */
  if (empty($_SESSION['name'])) {
   $data['ans'] = 0;
  } else {
   $data['ans'] = 1;
   $data['login'] = $_SESSION['name'];
   $msg_row = mysql_fetch_array(mysql_query("SELECT `post_id` FROM `post` ORDER BY `post_id` ASC"));
   $data['id'] = $msg_row['post_id'];
  }
  echo json_encode($data); // Отправляем данные в формате json
  exit;
}
/* Если переменная $name не пуста, то выполняем код */
if (!empty($name)) {
  /* Ищем игрока в БД */
  $sql = mysql_query("SELECT * FROM `users` WHERE `user_name`='".$name."'");
  if (mysql_num_rows($sql) == 0) {
   /* Если не находим, то создаем новую запись, запоминаем логин и передаем клиенту логин и id последнего сообщения */
   mysql_query("INSERT INTO `users` (`user_name`,`user_online`,`last_update`) VALUES ('".$name."','1','".time()."')");
   $data['ans'] = 0;
   $_SESSION['name'] = $name;
   $data['login'] = $_SESSION['name'];
   $msg_row = mysql_fetch_array(mysql_query("SELECT `post_id` FROM `post` ORDER BY `post_id` ASC"));
   $data['id'] = $msg_row['post_id'];
  } else {
   /* Если игрок в БД уже есть, то проверяем онлайн он или нет. Если онлайн, то выдаем ошибку, если нет, то делаем его онлайн и передаем нужные данные клиенту */
   $row = mysql_fetch_array($sql);
   if ($row['user_online'] == 0) {
    mysql_query("UPDATE `users` SET `user_online`='1' WHERE `user_name`='".$name."'");
    $data['ans'] = 0;
    $data['login'] = $_SESSION['name'];
    $msg_row = mysql_fetch_array(mysql_query("SELECT `post_id` FROM `post` ORDER BY `post_id` ASC"));
    $data['id'] = $msg_row['post_id'];
   } else {
    $data['ans'] = 1;
   }
  }
  echo json_encode($data);
  exit;
}
/* Получение нового сообщения */
if (!empty($msg)) {
  if (empty($msg)) { /* Если переменная пуста, то возвращаем 0 */
   $data['ans'] = 0;
  } else { /* В другом случае записываем в БД сообщение, обновляем запись игрока в БД (указываем что игрок онлайн и обновляем время последнего действия, нужно для отслеживания игроков онлайн) и отправляем нужные данные клиенту */
   $t = time();
   mysql_query("INSERT INTO `post` (`post_login`,`post_time`,`post_txt`) VALUES ('".$_SESSION['name']."','".$t."','".$msg."')");
   mysql_query("UPDATE `users` SET `last_update`='".$t."', `user_online`='1' WHERE `user_name`='".$_SESSION['name']."'");
   $data['ans'] = 1;
   $data['login'] = $_SESSION['name'];
   $data['time'] = date('H:i:s', $t);
   $data['msg'] = $msg;
  }
  echo json_encode($data);
  exit;
}
/* Если переменная $update не пуста (функция обновления на стороне клиента) */
if (!empty($update)) {
  if (empty($update)) {
   $data['ans'] = 0;
  } else {
   /* Выбираем всех игроков с базы */
   $user = mysql_query("SELECT * FROM `users`");
   $data['user'] = "";
   while ($user_row = mysql_fetch_array($user)) {
    /* Если игрок онлайн, то проверяем время его последнего действия и добавляем к нему 1 час (3600 сек) и запоминаем для передачи его имени клиенту. Если игрок в течении часа ничего не делал, то переводим его в режим оффлайн и убираем из списка игроков. Перевод игрока в режим оффлайн будет состоятся только в том случае если хоть 1 пользователь будет находится в чате. */
    if ($user_row['user_online'] == 1) {
     $t = $user_row['last_update']+3600;
     if ($t >= time()) {
      $data['user'] .= "<div>".$user_row['user_name']."</div>";
     } else {
      mysql_query("UPDATE `users` SET `user_online`='0' WHERE `user_name`='".$user_row['user_name']."'");
     }
    }
   }
   /* Выбираем все сообщения */
   $msg_sql = mysql_query("SELECT * FROM `post` ORDER BY `post_id` ASC");
   $data['msg'] = "";
   while ($msg_row = mysql_fetch_array($msg_sql)) {
    /* Производим проверку id. Если id игрока меньше чем id последнего сообщения, значит в БД появилось новое сообщение, выбираем его и запоминаем для передачи клиенту. Данное действие нужно для того что бы в чат клиенту добавлять по несколько сообщений, а не обновлять весь блок (div). Т.к. бывает нужно выделить какое то сообщение, а не можешь, т.к. блок обновляется и выделение сбрасывается. */
    if ($id < $msg_row['post_id']) {
     $data['msg'] .= "<div>[".date('H:i:s', $msg_row['post_time'])."] <strong>".$msg_row['post_login'].": </strong>".$msg_row['post_txt']."</div>";
     $data['id'] = $msg_row['post_id'];
    }
   }
  }
  echo json_encode($data);
  exit;
}

?>

База данных
Code
-- phpMyAdmin SQL Dump
-- version 3.2.3
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: Sep 28, 2011 at 05:40 PM
-- Server version: 5.1.40
-- PHP Version: 5.3.3

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";

--
-- Database: `chat`
--

-- --------------------------------------------------------

--
-- Table structure for table `post`
--

CREATE TABLE IF NOT EXISTS `post` (
   `post_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
   `post_login` varchar(50) NOT NULL,
   `post_time` int(10) NOT NULL,
   `post_txt` varchar(500) NOT NULL,
   PRIMARY KEY (`post_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

-- --------------------------------------------------------

--
-- Table structure for table `users`
--

CREATE TABLE IF NOT EXISTS `users` (
   `user_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
   `user_name` varchar(50) NOT NULL,
   `user_online` int(1) NOT NULL,
   `last_update` int(10) NOT NULL,
   PRIMARY KEY (`user_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Фух, вроде везде комментарии оставил, если что не понятно пишите.
Для более подробного понимания кода:
- html, css читаем тут: htmlbook
- jquery читаем тут: api.jquery.com либо задаем вопросы в теме.
Прикрепления: 5003472.png (24.7 Kb)
КластерДата: Среда, 28 Сентября 2011, 18:52 | Сообщение # 2
постоянный участник
Сейчас нет на сайте
Просто дополню русская документация по jQuery.

И для начинающих jQuery


Сообщение отредактировал Кластер - Среда, 28 Сентября 2011, 18:55
SektoidДата: Четверг, 29 Сентября 2011, 04:48 | Сообщение # 3
почетный гость
Сейчас нет на сайте
Спасибо
Хоть оно и не подойдет для моей игры, интересно было почитать.
Пеши есчо biggrin
AssasinДата: Четверг, 29 Сентября 2011, 09:40 | Сообщение # 4
web-coder
Сейчас нет на сайте
Тут описан процесс работы jquery (ajax) с php, можно изучить код и оптимизировать под свою игру.
SektoidДата: Четверг, 29 Сентября 2011, 13:36 | Сообщение # 5
почетный гость
Сейчас нет на сайте
Ну я это и имел ввиду - что в таком виде тупо вклеить его не получиться, но много полезной инфы из него вынести можно smile
AGENTX001Дата: Четверг, 29 Сентября 2011, 14:23 | Сообщение # 6
почётный гцупер
Сейчас нет на сайте
Assasin, у ты моя лапонька!!! Я с этим неделю маялся, и тут на тебе!) СПАСИБО!!
Or1ginalДата: Среда, 05 Октября 2011, 15:40 | Сообщение # 7
постоянный участник
Сейчас нет на сайте
Это из-за меня чтоли, я тебе в чат извини.. :DD
AssasinДата: Среда, 05 Октября 2011, 18:58 | Сообщение # 8
web-coder
Сейчас нет на сайте
Or1ginal, wink
Or1ginalДата: Четверг, 06 Октября 2011, 10:35 | Сообщение # 9
постоянный участник
Сейчас нет на сайте
А понятно, ну спасибо что простил smile

Сообщение отредактировал Or1ginal - Четверг, 06 Октября 2011, 10:36
KjutДата: Четверг, 06 Октября 2011, 10:35 | Сообщение # 10
почетный гость
Сейчас нет на сайте
Асасинчик молодец love

Портфолио
Команда Ninja World

Команде требуются художники
cougraAccДата: Суббота, 15 Октября 2011, 01:58 | Сообщение # 11
Яркая личность GD
Сейчас нет на сайте
Код отвратительный, верстка ужасная. Про js вообще молчу, такое ощущение что писал слепой калека. ТС ты бы книжки почитал...
p.s. tongue
AssasinДата: Суббота, 15 Октября 2011, 12:12 | Сообщение # 12
web-coder
Сейчас нет на сайте
cougraAcc, ты мне тут по возмущайся! Ишь, моду взял biggrin
ZelebobaДата: Воскресенье, 16 Октября 2011, 02:21 | Сообщение # 13
постоянный участник
Сейчас нет на сайте
Ну я бы не сказал что код прям таки ужасен... Пойдет для первого года обучения, но вот защита... Это уже совсем весело XD юзаем PDO и не паримся о скулях
cougraAccДата: Понедельник, 24 Октября 2011, 15:55 | Сообщение # 14
Яркая личность GD
Сейчас нет на сайте
На кол автора посадить ^_^. Такой код только для стенда "Как не нужно писать программы".

Добавлено (24.10.2011, 15:55)
---------------------------------------------
Шучу автор няшка heart , я любя придираюсь.

romgermanДата: Понедельник, 24 Октября 2011, 17:35 | Сообщение # 15
старожил
Сейчас нет на сайте
Ну jquery можно было бы не писать, просто вместо
Code
<script type="text/javascript" src="/style/jquery-1.6.2.min.js"></script>

можно написать
Code
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.min.js"></script>

И кстати я думаю не обязательно было пихать самую последнюю квери, даже 1.4 подошло бы.
cougraAccДата: Вторник, 25 Октября 2011, 03:06 | Сообщение # 16
Яркая личность GD
Сейчас нет на сайте
Quote (romgerman)
И кстати я думаю не обязательно было пихать самую последнюю квери, даже 1.4 подошло бы.

Когда ты работаешь в оффлайне, то брать либу с гугла не очень удобно.
romgermanДата: Вторник, 25 Октября 2011, 20:42 | Сообщение # 17
старожил
Сейчас нет на сайте
Ну мне всё равно, я просто выразил своё мнение и кастати такой урок есть здесь - http://ruseller.com/lessons.php?rub=32&id=758.
SouzNikДата: Среда, 25 Января 2012, 18:56 | Сообщение # 18
был не раз
Сейчас нет на сайте
Спасибо! Очень долго искал нормальный чат и наконец нашел!

---------------------------------------------
Заметил несколько дырок. Если пользователь раньше был зареган, то при входе в базе это все обновляется, а сам чел не может написать ничего. Страница заново просит логин. Для этого я сделал так:
В файле core.php надо заменить это:
Code

mysql_query("UPDATE users SET last_update = '".$t."', user_online = '1' WHERE user_name = '".$_SESSION['name']."'");   
$data['ans'] = 0;

На это:
Code

mysql_query("UPDATE users SET last_update = '".$t."', user_online = '1' WHERE user_name = '".$_SESSION['name']."'");   
$data['ans'] = 0;
$_SESSION['name'] = $name;


И так же я немного приукрасил)
Вот что у меня получилось:


Сообщение отредактировал SouzNik - Среда, 25 Января 2012, 18:57
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг