Создание PHP-AJAX чата

Приветствую!

Эта статья для тех кто желает сам сделать свой чат на php с применением ajax. В ней я расскажу о том как самому сделать простой чат.

Так будет выглядеть получившийся чат.

Необходимые знания:

  1. Начальные знания в php. Такие как: Как подключиться к базе данных mysql?
  2. Начальные знания в html и css.
  3. Начальные знания в JavaScript и jQuery. (даже если вы только слышали о jQuery, но не работали с ним)

Итак начнём!



Для начала создадим новую базу данных в MySQL и выполним SQL запрос:

CREATE TABLE `messages` (
  `id` int(5) NOT NULL AUTO_INCREMENT,
  `name` char(255) character SET utf8 NOT NULL,
  `text` text character SET utf8,
  PRIMARY KEY  (`id`)
);

В этой таблице у нас будут храниться сообщения чата.

  1. id – номер сообщения, он должен быть помечен как AUTO_INCREMENT для того что бы для каждого сообщения создавался уникальный индекс.
  2. name – имя пользователя отправившего сообщение
  3. text – само сообщение

Можно так же расширить список полей, например время сообщения, и так далее.

Теперь приступим к созданию клиентской части чата. Она у нас будет реализована в файле index.php:

<!-- Указываем DOCTYPE -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>PhpAjaxChat</title>
<!-- У нас всё работает в UTF-8 -->
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
 
<!-- Загружаем стили для чата -->
<link rel="stylesheet" type="text/css" media="screen" href="css.css" />
 
<!-- Подключаем jQuery -->
<script type="text/javascript" src="jquery.js"></script>
 
<!-- Сам код нашего чата -->
<script type="text/javascript">
 
$(document).ready(function () {
    $("#pac_form").submit(Send); // вешаем на форму с именем и сообщением событие которое срабатывает кодга нажата кнопка "Отправить" или "Enter"
    $("#pac_text").focus(); // по поле ввода сообщения ставим фокус
    setInterval("Load();", 2000); // создаём таймер который будет вызывать загрузку сообщений каждые 2 секунды (2000 миллисекунд)
});   
 
// Функция для отправки сообщения
function Send() {
    // Выполняем запрос к серверу с помощью jquery ajax: $.post(адрес, {параметры запроса}, функция которая вызывается по завершению запроса)
    $.post("ajax.php", 
        {
        act: "send",  // указываем скрипту, что мы отправляем новое сообщение и его нужно записать
        name: $("#pac_name").val(), // имя пользователя
        text: $("#pac_text").val() //  сам текст сообщения
    },
     Load ); // по завершению отправки вызываем функцию загрузки новых сообщений Load()
 
    $("#pac_text").val(""); // очистим поле ввода сообщения
    $("#pac_text").focus(); // и поставим на него фокус
 
    return false; // очень важно из Send() вернуть false. Если этого не сделать то произойдёт отправка нашей формы, те страница перезагрузится
}
 
var last_message_id = 0; // номер последнего сообщения, что получил пользователь
var load_in_process = false; // можем ли мы выполнять сейчас загрузку сообщений. Сначала стоит false, что значит - да, можем
 
// Функция для загрузки сообщений
function Load() {
    // Проверяем можем ли мы загружать сообщения. Это сделано для того, чтобы мы не начали загрузку заново, если старая загрузка ещё не закончилась.
    if(!load_in_process)
    {
            load_in_process = true; // загрузка началась
            // отсылаем запрос серверу, который вернёт нам javascript
            $.post("ajax.php",
            {
                  act: "load", // указываем на то что это загрузка сообщений
                  last: last_message_id, // передаём номер последнего сообщения который получил пользователь в прошлую загрузку
                  rand: (new Date()).getTime()
            },
               function (result) { // в эту функцию в качестве параметра передаётся javascript код, который мы должны выполнить
                    eval(result); // выполняем скрипт полученный от сервера
                    $(".chat").scrollTop($(".chat").get(0).scrollHeight); // прокручиваем сообщения вниз
                    load_in_process = false; // говорим что загрузка закончилась, можем теперь начать новую загрузку
            });
    }
}
</script>
 
<body>
<div style="padding: 100px;">
<h1>Php Ajax Chat</h1>
<!-- Вот в этих 2-х div-ах будут идти наши сообщения из чата -->
<div class="chat r4">
<div id="chat_area"><!-- Сюда мы будем добавлять новые сообщения --></div>
</div>
<form id="pac_form" action=""><!-- Наша форма с именем, сообщением и кнопкой для отправки -->
<table style="width: 100%;">
        <tr>
                <td>Имя:</td>
                <td>Сообщение:</td>
                <td></td>
        </tr>
        <tr>
                <!-- Поле ввода имени -->
                <td><input type="text" id="pac_name" class="r4" value="Гость"></td>
 
                <!-- Поле ввода сообщения -->
                <td style="width: 80%;"><input type="text" id="pac_text" class="r4" value=""></td>
 
                <!-- Кнопка "Отправить" -->
                <td><input type="submit" value="Отправить"></td>
        </tr>
</table>
</form>
 
</div>
</body>
</html>

css.css:

* {
        margin: 0;
        padding: 0;
}
 
body {
        font: normal normal normal 16px "Trebuchet MS", Arial, Times;
        color: #000000;
}
 
/* Важное свойство */
.chat {
        height: 500px;
        overflow: auto; /* Это позволяет отображать полосу прокрутки */
        position: relative; /* Это позволяет съезжать тексту в слое, не растягивая страницу */
        text-align: left;
        border: solid #818181 1px;
}
 
.chat div {
        position: absolute; /* Страница остаётся того же размера */
}
 
.chat span {
        display: block;
}
 
input[type=text],textarea {
        width: 100%;
        font: normal normal normal 16px "Trebuchet MS", Arial, Times;
        border: solid #818181 1px;
}
 
/* Для CSS 3 */
.r4 {
        -moz-border-radius: 4px;
        -khtml-border-radius: 4px;
        -webkit-border-radius: 4px;
        border-radius: 4px;
}

Теперь приступим к созданию серверной части чата ajax.php:

<?php
// настройки для подключения к MySQl
$config = array( 'hostname' => 'localhost', 'username' => 'root', 'password' => '', 'dbname' => 'pacdb' );
 
// подключаемся к MySQL, если не вышло то выходим
if( !mysql_connect($config['hostname'], $config['username'], $config['password']) )
{
        exit();
}
// Выбираем базу данных, если не вышло то выходим
if( !mysql_select_db($config['dbname']) )
{
        exit();
}
mysql_query("SET NAMES 'utf8'"); // говорим MySQl'у то что мы будем работать с UTF-8
 
Header("Cache-Control: no-cache, must-revalidate"); // говорим браузеру что-бы он не кешировал эту страницу
Header("Pragma: no-cache");
 
Header("Content-Type: text/javascript; charset=utf-8"); // говорим браузеру что это javascript в кодировке UTF-8
 
// проверяем есть ли переменная act (send или load), которая указываем нам что делать
if( isset($_POST['act']) )
{
        // $_POST['act'] - существует
        switch ($_POST['act'])
        {
                case "send" : // если она равняется send, вызываем функцию Send()
                        Send();
                        break;
                case "load" : // если она равняется load, вызываем функцию Load()
                        Load();
                        break;
                default : // если ни тому и не другому  - выходим
                        exit();
        }
}
 
// Функция выполняем сохранение сообщения в базе данных
function Send()
{
        // тут мы получили две переменные переданные нашим java-скриптом при помощи ajax
        // это:  $_POST['name'] - имя пользователя
        // и $_POST['text'] - сообщение
 
        $name = substr($_POST['name'], 0, 200); // обрезаем до 200 символов
        $name = htmlspecialchars($name); // заменяем опасные теги (<h1>,<br>, и прочие) на безопасные
        $name = mysql_real_escape_string($name); // функция экранирует все спец-символы в unescaped_string , вследствие чего, её можно безопасно использовать в mysql_query()
 
        $text = substr($_POST['text'], 0, 200); // обрезаем до 200 символов
        $text = htmlspecialchars($text); // заменяем опасные теги (<h1>,<br>, и прочие) на безопасные
        $text = mysql_real_escape_string($text); // функция экранирует все спец-символы в unescaped_string , вследствие чего, её можно безопасно использовать в mysql_query()
 
        // добавляем новую запись в таблицу messages
        mysql_query("INSERT INTO messages (name,text) VALUES ('" . $name . "', '" . $text . "')");
}
 
 
// функция выполняем загрузку сообщений из базы данных и отправку их пользователю через ajax виде java-скрипта
function Load()
{
        // тут мы получили переменную переданную нашим java-скриптом при помощи ajax
        // это:  $_POST['last'] - номер последнего сообщения которое загрузилось у пользователя
 
        $last_message_id = intval($_POST['last']); // возвращает целое значение переменной
 
        // выполняем запрос к базе данных для получения 10 сообщений последних сообщений с номером большим чем $last_message_id
        $query = mysql_query("SELECT * FROM messages WHERE ( id > $last_message_id ) ORDER BY id DESC LIMIT 10");
 
        // проверяем есть ли какие-нибудь новые сообщения
        if( mysql_num_rows($query) > 0 )
        {
                // начинаем формировать javascript который мы передадим клиенту
                $js = 'var chat = $("#chat_area");'; // получаем "указатель" на div, в который мы добавим новые сообщения
 
                // следующий конструкцией мы получаем массив сообщений из нашего запроса
                $messages = array();
                while ( $row = mysql_fetch_array($query) )
                {
                        $messages[] = $row;
                }
 
                // записываем номер последнего сообщения
                // [0] - это вернёт нам первый элемент в массиве $messages, но так как мы выполнили запрос с параметром "DESC" (в обратном порядке),
                // то это получается номер последнего сообщения в базе данных
                $last_message_id = $messages[0]['id'];
 
                // переворачиваем массив (теперь он в правильном порядке)
                $messages = array_reverse($messages);
 
                // идём по всем элементам массива $messages
                foreach ( $messages as $value )
                {
                        // продолжаем формировать скрипт для отправки пользователю
                        $js .= 'chat.append("<span>' . $value['name'] . '&raquo; ' . $value['text'] . '</span>");'; // добавить сообщние (<span>Имя &raquo; текст сообщения</span>) в наш div
                }
 
                $js .= "last_message_id = $last_message_id;"; // запишем номер последнего полученного сообщения, что бы в следующий раз начать загрузку с этого сообщения
 
                // отправляем полученный код пользователю, где он будет выполнен при помощи функции eval()
                echo $js;
        }
}
?>

Чат готов!
Скачать чат можно тут.
А полноценный чат тут: ElfChat =)

Комментарии (53)

Fortm@x

Быстро и просто, то что надо для старта Gooooooooood =)

SaT

Спасибо большое за статейку, давно такую искал.

SaT

А кто нибудь может написать дополнение такое как авторизация, максимально простая, типа введите ник и пароль и регистрация типа ник введите, пароль и подтверждение пароля.

SaT, это уже достаточно просто, в одном из следующих своих постов я расскажу как сделать авторизацию (и не только для чата, а для любого скрипта)

SaT

Elfet, вау круто, спасибо, буду ждать.

SaT

Ещё подскажите пож. литературу по изучению PHP и AJAX.

SaT, посмотрите вот это: PHP5 (серия «В подлиннике»). Авторы: Д. Котеров, А. Костарев.
Очень хорошая книга.

Статья конечно хороша, как и женщина в шапке. Но когда же ждать 5ю версию чата?)

По просьбе начал писать статью как раз на эту тематику, а тут кидают ссылку и вижу, что у меня тоже самое почти получалось -) Статью писать передумал, т.к. у тебя довольно хорошая реализация!
Лично мне статья не пригодилась, но другим она очень пригодиться! Спасибо за полезный контент для людей!

Evil

А как сделать звуки при добавление сообщение?

Воспользоваться какими-нибудь библиотеками для работы со звуком. Например: http://plugins.jquery.com/project/sound

Отличный чат получается )

SaT

Ты как чат до делаешь ссылочку на него дай.

Спасибо! Классная статья, очень помогла понять, что такое ajax!
Огромнейшее спасибо…

Хотелось бы очень статью об авторизации….тоже очень жду.

А как сделать привязку клиента к сессии какого-нибудь phpbb?

Fog, аааа, это вот уже нужно хитро делать. Например так как у меня в чате сделано :)

Если я правильно понял, нужно подключить библиотеки phpbb, узнать sid и userrname.
В чём хитрость? Может, намекнёте, в какую сторону копать?
Я правильно понимаю, делается проверка на $user->data['user_id'] != ANONYMOUS
потом берётся $user->data['user_name']
Или я не прав?

Ну, вроде бы так :)

Andrey

Странное явление наблюдается. Сделал чат по вашему примеру.
с заголовком Header(«Content-Type: text/javascript; charset=utf-8″);
все сообщения выводятся по 2 раза подряд. При этом в базу записывается одно.
Если в заголовке заменить text/javascript на text/html то выводится все нормально 1 раз. Вы не знаете в чем тут собака порылась?

При перезагрузке чата сообщения дублируются тоже, но в другом порядке:
Вася: 123
Вася : 123
Петя: 321
Петя: 321
После перезагрузки:
Вася: 123
Петя: 321
Вася: 123
Петя: 321

Вероятно где-то ошибка была допущена.

Andrey

Похоже на то, что при Header(«Content-Type: text/javascript; charset=utf-8″);
скрипт выполняется и без eval(result). А функция eval его дублирует.

Andrey

В любом случае спасибо большое за статью, узнал для себя много нового.
А по поводу дублежа, похоже jquery смотрит возвращаемый заголовки и при text/javascript
делает eval сама.

Да, действительно, может быть и так. Нужно посмотреть что там в новой версии jQuery сделали. :)

maxim

Почему то не выводит сообщение из базы данных, и никаких ошибок нет =(

Andrey

2 maxim
Скорее всего ошибка где-то у вас.
напишите alert(result); перед строчкой eval(result); Посмотрите вообще доходит дело до этой функции.

maxim

2Andrey
файлы php были в утф-8 и не отоброжалось, сохранил в другой кодировке и заработало

Николай

такое дело..
я попробовал добавить уменьшенную копию этого чата в левый блок сайта (под меню) почти в конце страницы…
и теперь когда я перезагружаю страницу браузер позиционируется на чате в конце страницы.
как можно от этого избавиться

Николай

а усё понял … надо из скрипта удалить строчку
$(«#pac_text»).focus();

vovan

Есть спецы которые могут подсказать.
1.Есть папка с файлами (чат).Как мне из этих папок
или файлов сделать базу данных?
2.Можно по другому поставить вопрос; есть папка (чат)
в ней папки ( client, server, doc),на компе чат работает,потому как при распаковке
чат.exe установился виртуальный сервер .Все работает,на локальном компе замечательно.
Когда я сливаю папку чата на сервер – не работает.Я так понимаю нужна своя база данных на сервере??? Или как все это настроить???

Elfet

Что за чат такой? =)

vovan

Флеш чат,обыкновенный как и все чаты, только ему нужен сервер.

vovan

Elfet -Если ты хорошо разбираешся то вот ссылка -http://www.123flashchat.com
может быть ты разберешся раз уж ты щелкаеш чаты как орешки ,а то админы на хосте отмораживаются говорят что чаты запрещены
покупай виртуальный и там может быть разместим

Если ему нужен сервер, то нужно покупать vpn

vovan

Ето что такое?

Правильно ли я понимаю, что здесь используется jquery? Как перевести этот исходник для кодировки сp-1251 ?

Есть ли в инэте чаты на основе этого? Дайте ссылочек на эти чаты интересно посмотреть.

SaT, где-то видел один чат. Вроде STRchat называется. Он ещё с моей 3-ки переделан.

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

DEE DEE

Статья супер! Автору респект и уважуха!)))

Спасибо за урок, буду делать чут на Аяксе)))

Пожалуйста :)

У меня кодировка windows-1251 и проблема возникает только в Опере, выдаёт иероглифы
в скрипте сохранения в БД соответственно
header(«Content-Type: text/html; charset=windows-1251″);

Ну видимо какая-то проблема с кодировкой :) Зачем вам windows-1251 использовать? Сейчас весь мир переходит на UTF-8

AleX

В чём здесь ошибка:

$.post(document.location.href+»ajax.php»,
{
act: «send», // указываем скрипту, что мы отправляем новое сообщение и его нужно записать
name: $(«#pac_name»).val(), // имя пользователя
text: $(«#pac_text»).val() // сам текст сообщения

$.post(«ajax.php»,
{
act: «send», // указываем скрипту, что мы отправляем новое сообщение и его нужно записать
name: $(«#pac_name»).val(), // имя пользователя
text: $(«#pac_text»).val() // сам текст сообщения
},
Load );

AleX

$.post(document.location.href+«ajax.php»
мне нужен абсолютный путь к ajax.php

Anuar

Конечно, всё хорошо. И написао тоже отлично. А вот авторизация сущий пустяк. Даже можно сделать чтобы при след.входе на сайт, он автомотически был авторизован. НАпример реализовать это можно через Cookies.

Вадим

А где же описание jquery.js? Написано «Начальные знания в JavaScript и jQuery. (даже если вы только слышали о jQuery, но не работали с ним)»….Скачав сам чат, открыл файл jquery.js и стало жутковато)))

А зачем вы лезите в сам файл jquery.js? Если нужно девеломерская версия этого плагина – можите скачать её с их сайта.

Alex

Чат отличный!
Написан кратко и лаконично.
Только, как было упомянуто выше, нужно вместо eval(result) написать просто result.

СПАСИБО ОГРОМНОЕ!!!!
Никак не мог найти нормальный чат, везде с прибамбасами всякими или с ошибками, а тут все норм.
СПАСИБО!!!

О!! Тема! Автору +++

Вы можете следить за обсуждением этой записи с помощью RSS

Оставить комментарий





Подтвердите, что Вы не бот — выберите человечка с поднятой рукой:

Рубрики



Ссылки


наверх