Урок по созданию чата на 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 либо задаем вопросы в теме.
|
|
| |
Кластер | Дата: Среда, 28 Сентября 2011, 18:52 | Сообщение # 2 |
постоянный участник
Сейчас нет на сайте
| Просто дополню русская документация по jQuery.
И для начинающих jQuery
Сообщение отредактировал Кластер - Среда, 28 Сентября 2011, 18:55 |
|
| |
Sektoid | Дата: Четверг, 29 Сентября 2011, 04:48 | Сообщение # 3 |
почетный гость
Сейчас нет на сайте
| Спасибо Хоть оно и не подойдет для моей игры, интересно было почитать. Пеши есчо
|
|
| |
Assasin | Дата: Четверг, 29 Сентября 2011, 09:40 | Сообщение # 4 |
web-coder
Сейчас нет на сайте
| Тут описан процесс работы jquery (ajax) с php, можно изучить код и оптимизировать под свою игру.
|
|
| |
Sektoid | Дата: Четверг, 29 Сентября 2011, 13:36 | Сообщение # 5 |
почетный гость
Сейчас нет на сайте
| Ну я это и имел ввиду - что в таком виде тупо вклеить его не получиться, но много полезной инфы из него вынести можно
|
|
| |
AGENTX001 | Дата: Четверг, 29 Сентября 2011, 14:23 | Сообщение # 6 |
почётный гцупер
Сейчас нет на сайте
| Assasin, у ты моя лапонька!!! Я с этим неделю маялся, и тут на тебе!) СПАСИБО!!
|
|
| |
Or1ginal | Дата: Среда, 05 Октября 2011, 15:40 | Сообщение # 7 |
постоянный участник
Сейчас нет на сайте
| Это из-за меня чтоли, я тебе в чат извини.. :DD
|
|
| |
Assasin | Дата: Среда, 05 Октября 2011, 18:58 | Сообщение # 8 |
web-coder
Сейчас нет на сайте
| Or1ginal,
|
|
| |
Or1ginal | Дата: Четверг, 06 Октября 2011, 10:35 | Сообщение # 9 |
постоянный участник
Сейчас нет на сайте
| А понятно, ну спасибо что простил
Сообщение отредактировал Or1ginal - Четверг, 06 Октября 2011, 10:36 |
|
| |
Kjut | Дата: Четверг, 06 Октября 2011, 10:35 | Сообщение # 10 |
почетный гость
Сейчас нет на сайте
| Асасинчик молодец
Портфолио Команда Ninja World
Команде требуются художники
|
|
| |
cougraAcc | Дата: Суббота, 15 Октября 2011, 01:58 | Сообщение # 11 |
Яркая личность GD
Сейчас нет на сайте
| Код отвратительный, верстка ужасная. Про js вообще молчу, такое ощущение что писал слепой калека. ТС ты бы книжки почитал... p.s.
|
|
| |
Assasin | Дата: Суббота, 15 Октября 2011, 12:12 | Сообщение # 12 |
web-coder
Сейчас нет на сайте
| cougraAcc, ты мне тут по возмущайся! Ишь, моду взял
|
|
| |
Zeleboba | Дата: Воскресенье, 16 Октября 2011, 02:21 | Сообщение # 13 |
постоянный участник
Сейчас нет на сайте
| Ну я бы не сказал что код прям таки ужасен... Пойдет для первого года обучения, но вот защита... Это уже совсем весело XD юзаем PDO и не паримся о скулях
|
|
| |
cougraAcc | Дата: Понедельник, 24 Октября 2011, 15:55 | Сообщение # 14 |
Яркая личность GD
Сейчас нет на сайте
| На кол автора посадить ^_^. Такой код только для стенда "Как не нужно писать программы". Добавлено (24.10.2011, 15:55) --------------------------------------------- Шучу автор няшка , я любя придираюсь.
|
|
| |
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 |
|
| |
|