AJAX веб чат с использованием PHP, MySQL и jQuery (Часть 1 из 2-х)
Как обычно первый шаг посвящен разметке HTML. Наш документ строится в соответствии с HTML5, что позволяет использовать новый, более короткий синтаксис DOCTYPE, и опускать атрибут type в тегах script.
index.html
Для оптимизации загрузки, стили включены в секции head, а файлы JavaScript подключаются внизу документа, перед закрывающим тегом body.
Для организации прокручиваемой области со строками чата мы используем плагин jScrollPane. Данный плагин имеет свои собственные стили, который включаются в секции head.
Разметка чата состоит из четырех основных элементов div – верхней панели, контейнера чата, контейнера пользователей и нижней панели. Последний div содержит формы для регистрации пользователя и отправки сообщения. Форма отправки сообщения по умолчанию скрыта и выводится, только если пользователь успешно вошел в систему чата.
Затем мы включаем файлы JavaScript: библиотеку jQuery, плагин mousewheel (используется в jScrollPane), плагин jScrollPane и наш файл script.js.
Схема базы данных
Прежде чем перейти к части PHP, нужно сначала взглянуть на организацию данных чата в базе данных MySQL.
Для нашего скрипта мы используем две таблицы. В таблице webchat_users хранится информация об участниках чата. Таблица имеет поля id, name, gravatar и last_activity. Поле name определено как уникальное, таким образом предотвращается использование дублирующихся имен в чате.
Другим полезным свойством поля с уникальным индексом является то, что запрос на вставку данных завершится с ошибкой и свойство inserted_rows объекта MySQLi будет установлено в значение 0, если попытаться вставить дублирующиеся строки. В классе PHP Chat данное свойство будет активно использоваться.
Поле last_activity содержит значение времени. Значение обновляется каждые 15 секунд для каждого пользователя. Поле также определено как индекс, что позволяет быстро удалять неактивных пользователей (значение в поле last_activity более 15 означает, что пользователь более не просматривает окно чата).
Таблица webchat_lines содержит записи в чате. Заметьте, что мы храним имя автора и gravatar здесь тоже. Такое дублирование позволяет нам отказаться от использования затратной директивы join при запросе последних записей – наиболее часто используемых в нашем приложении.
Определения таблиц имеются в файле tables.sql в исходниках. Вы можете использовать текст запросов для создания таблиц. Также, при установке чата на свой хост, нужно поменять установки в ajax.php на ваши данные для соединения с базой MySQL.
Теперь у нас есть база данных, давайте обсудим скрипт PHP, который управляет чатом.
Первый файл, который мы рассмотрим, ajax.php. Он обрабатывает запросы AJAX от клиентской части из jQuery и выводит данные в формате JSON.
ajax.php
Для удобства используется оператор switch для определения действий, которые обрабатывает скрипт. Здесь реализованы подсистемы чата, функциональность входа/выхода и действия по запросу списка реплик и пользователей в режиме онлайн.
Вывод осуществляется в форме сообщений JSON (которые удобно обрабатывать с помощью jQuery), ошибки генерируют исключения. Оператор switch распределяет все запросы соответствующим статическим методам класса Chat, который будет обсуждаться позже в данном разделе.
DB.class.php
Остальная часть класса реализует коммуникацию с базой данных, в основе которой лежит статический метод query().
ChatBase.class.php
ChatLine.class.php
Класс ChatLine является производным классом от ChatBase. Объект данного класса может быть легко создан с помощью передачи конструктору массива с текстом, именем автора и элементом gravatar. Свойство класса gravatar содержит хэш md5 email адреса. Оно нужно для получения пользовательского аватара, соответствующего email адресу, с сайта gravatar.com.
Данный класс также определяет метод save, который сохраняет объект в базе данных. Так как метод возвращает объект MySQLi, содержащийся в классе DB, вы можете проверить успешность завершения операции с помощью свойства affected_rows.
ChatUser.class.php
Класс имеет свойства name и gravatar (обратите внимание на модификатор доступа protected – свойства доступны в классе ChatBase, и мы можем устанавливать их значения в конструкторе).
В классе определен метод update(), который обновляет поле last_activity значением текущего времени. Таким образом показывается, что пользователь держит окно с чатом отрытым и его надо учитывать как автора в режиме онлайн.
Chat.class.php – Часть 1
Этот код выполняет всю работу. В операторе switch в файле ajax.php выбирались действия, которые соответствовали методам данного класса. Каждый из этих методов возвращает массив, который затем конвертируется в объект JSON с помощью функции json_encode() (это происходит внизу в файле ajax.php).
Когда пользователь входит в систему, его имя и gravatar сохраняются как элементы массива $_SESSION и становятся доступны в последующих запросах.
Chat.class.php – Часть 2
jQuery отправляет запросы getUsers() каждые 15 секунд. Мы используем данный факт, чтобы удалить реплики, которые старше 5 минут и неактивных пользователей из базы данных. Потенциально можно было бы удалять данные записи в getChats, но этот запрос поступает каждую секунду и дополнительная нагрузка может повлиять на производительность приложения.
В методе getChats() используется функция gmdate вывода времени в формате GMT. В клиентской части мы используем значения часов и минут для установки в объекте JavaScript, а в результате время отображается в соответствии с часовым поясом пользователя.
Продолжение во второй части!
Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: tutorialzine.com/2010/10/ajax-web-chat-php-mysql/
Перевел: Сергей Фастунов
Урок создан: 3 Ноября 2010
Просмотров: 139047
Правила перепечатки
5 последних уроков рубрики «PHP»
Фильтрация данных с помощью zend-filter
Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.
Контекстное экранирование с помощью zend-escaper
Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.
Подключение Zend модулей к Expressive
Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.
Совет: отправка информации в Google Analytics через API
Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.
Подборка PHP песочниц
Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.
Как сделать чат
Думаю, что каждый из Вас знает, что такое чат. И очень часто на сайтах можно встретить либо маленькие чаты, либо достаточно большие и сложные. В этой статье я опишу принцип создания чата. Обратите внимание, что в этой статье не будет готового кода «скопировал-вставил«, а только алгоритм, с помощью которого Вы, обладая необходимыми знаниями, сможете сделать чат.
Ключевая особенность чата в том, что его содержимое обновляется автоматически. Отсюда и возникают все трудности.
Для начала разберём с Вами структуру таблицы в базе данных. Вот те поля, которые обязательно потребуются:
Безусловно, это только пример. Вы можете добавлять ещё массу других полей, тем самым, расширяя возможности Вашего чата.
Теперь необходимо вывести HTML-код:
В данном коде опять же всё как пример. Можно всё смело менять, но принцип должен быть тем же: есть место, где выводятся сообщения, причём они выводятся в одинаковом виде. Вместе с полем, где выводятся сообщения, есть текстовое поле и кнопка «Отправить«.
Обязательно для блока chat поставьте фиксированную высоту, чтобы при добавлении новых сообщений, у Вас этот блок не вырастал, также поставьте полосу прокрутки у него, чтобы можно было просмотреть все сообщения. Всё это делается с помощью CSS.
Теперь займёмся JavaScript:
И, наконец, PHP-код (добавление новых сообщений):
Всё, круг замкнулся, и чат заработал. Как видите, сделать чат достаточно сложно и нужно обладать большим багажом знаний. Но я надеюсь, что данная статья здорово облегчит Вам эту задачу. Абсолютно любой чат, какой бы он сложный ни был, основан на принципах, описанных в данной статье, поэтому смело можете его использовать как каркас.
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Комментарии ( 25 ):
Спасибо за статью, Михаил! Но ведь можно сделать и без применения js?
Можно, с применением frame. Но это очень плохой вариант в том плане, что, во-первых, будет «моргать» экран, поскольку обновляется целиком весь блок, особенно это будет заметно на медленных компьютерах. Также очень сильно ограничена функциональность и многое нельзя будет сделать.
Можно взять готовый скрипт чата. Минусов масса, но если ничего не знаете, то это единственный вариант.
Михаил а как сделать так чтоб аякс запрос, проверял есть ли новые сообщения, если есть то уже подгружает, а если нет то нет. как вот сделать эту проверку? Сама структура запроса не ясна. пожалуйста обьясните.
Отправлять вместе с запросом id последнего сообщения, например. Если новое появилось, то возвращать результат.
Если беспокоитесь о безопасности, то можете и так сделать. Как альтернатива, можете передавать не id, а время последнего обновления. Тогда выводить только сообщения, отправленные позже этого времени.
Можно сделать асинхронную подгрузку сообщений если не беспокоетесь о нагрузке
Я сделал чат по такому же принципу, только я не знал как обновлять и узнал здесь. Спасибо.
Михаил, а как сделать так, чтобы при обновлении страницы все сообщения из окна чата исчезали? Т.е. каждый новый пользователь не видел сообщений старых. И если это вообще возможно, то где хранить сообщения в БД или в файлах… Спасибо
Можно хранить в cookie дату первого посещения чата и выводить сообщения только, отправленные позже этого времени.
у меня вопрос) я не разбирал код честно говоря, просмотрел поверхностно) но как быть в случае когда нужно показывать 100 сообщений, тогда контент страницы требует прокрутку) и вид вовсе не компактный, как решить эту проблему? просто не хочу курить форумы))
Через CSS у блока можно поставить максимальную высоту и прокрутку.
спасибо) просто не сталкивался с прокруткой) обязательно попробую)
Михаил, вы пишите статьи для людей или для поисковиков?
В первую очередь, для людей. Для поисковиков только ставлю.
Михаил, спасибо за статью. Вопрос: мне нужно установить, уже готовый чат Mibew Messenger.Все понятно, но там нужно создать БД MySQL и БД пользователя, где это создавать и как? управление сайта через самописную cms. В примере БД создаются в phpMyAdmin.
Для создания пользователя и БД используйте все тот же phpMyAdmin
Как создать простое приложение веб-чата
В этом уроке мы будем создавать простое приложение веб-чата с помощью PHP и jQuery. Утилита такого типа прекрасно подойдет для системы онлайн-поддержки вашего сайта.
Введение

Приложение чата, которое мы сегодня построим, будет довольно простым. Оно будет включать в себя систему входа и выхода, возможности в AJAX-стиле, а также предложит поддержку нескольких пользователей.
Шаг 1: HTML разметка
Мы начнем этот урок с создания нашего первого файла index.php.
Шаг 2: Создание стиля CSS
Теперь мы добавим немного css, чтобы заставить наше приложение чата выглядеть лучше, чем стиль браузера по умолчанию. Код, указанный ниже будет добавлен в наш файл style.css.
В вышеуказанном css нет ничего особенного, кроме того факта, что некоторые id или классы, для которых мы устанавливаем стиль, будут добавлены немного позже.

Как вы можете видеть выше, мы закончили строить пользовательский интерфейс чата.
Шаг 3: Используем PHP, чтобы создать форму входа.
Теперь мы реализуем простую форму, которая будет спрашивать у пользователя его имя, перед тем, как пустить его дальше.
Отображение формы входа
Для того, чтобы показать форму логина в случае, если пользователь не вошел в систему, и следовательно, не сессия не создалась, мы используем другую инструкцию if else вокруг блока-обертки #wrapper div и тагов скрипта в нашем исходном коде. В противоположном случае, если пользователь вошел в систему и создал сессию, этот код спрячет форму входа и покажет окно чата.

Приветствие и меню выхода из системы
Мы еще не закончили создавать систему входа для этого приложения чата. Нам еще нужно дать пользователю возможность выйти из системы и закончить сессию чата. Как вы помните, наша исходная HTML разметка включала в себя простое меню. Давайте вернемся назад и добавим некоторый PHP код, который придаст меню больше функциональности.
Прежде всего, давайте добавим имя пользователя в сообщение приветствия. Мы сделаем это, выводя сессию имени пользователя.

Для того, чтобы позволить пользователю выйти из системы и завершить сессию, мы прыгнем выше головы и кратко используем jQuery.
Код jquery, приведенный выше просто показывает диалог подтверждения, если пользователь кликнет по ссылке выхода #exit. Если пользователь подтвердит выход, тем самым решив закончить сессию, мы отправим его в index.php?logout=true. Это просто создаст переменную с именем logout со значением true. Мы должны перехватить эту переменную с помощью PHP:

Теперь мы увидим, существует ли get переменная ‘logout’, используя функцию isset(). Если переменная была передана через url, такой, как ссылка, упомянутая выше, мы переходим к завершению сессии пользователя с текущим именем.
Перед уничтожением сессии пользователя с текущим именем с помощью функции session_destroy() мы хотим выводить простое сообщение о выходе в лог чата. В нем будет сказано, что пользователь покинул сессию чата. Мы сделаем это, используя функции fopen(), fwrite() и fclose(), чтобы манипулировать нашим файлом log.html, который, как мы увидим позднее, будет создан в качестве лога нашего чата. Пожалуйста, обратите внимание, что мы добавили класс ‘msgln’ в блок div. Мы уж определили стиль css для этого блока.
Проделав это, мы уничтожаем сессию и перенаправляем пользователя на ту же страницу, где появится форма входа в систему.
Шаг 4: Поддержка пользовательского ввода данных
После того, как пользователь подтвердил свои действия в нашей форме, нам нужно захватывать его ввод с клавиатуры и писать его в лог нашего чата. Для того, чтобы сделать это, мы должны использовать jQuery и PHP, чтобы работать синхронно на стороне сервера и на стороне клиента.
jQuery
Практически все, что мы собираемся делать с jQuery для обработки наших данных, будет вращаться вокруг запроса на jQuery post.
Пожалуйста обратите внимание, что код, указанный выше, пойдет в наш таг скрипта, где мы поместили jQuery код выхода из системы.
На данный момент мы имеем данные POST, отправляемые в файл post.php каждый раз, когда пользователь отправляет форму и посылает новое сообщение. Наша задача теперь захватить эти данные и записать их в лог нашего чата.
И наконец, мы закрываем наш файл с помощью fclose().
Шаг 5: Отображение содержимого лога чата (log.html)
Чтобы сэкономить нам немного времени, мы предварительно загрузим лог чата в блок #chatbox div, как если бы он что-то содержал.
Мы используем процедуру, похожую на ту, что мы использовали в файле post.php, но на этот раз мы только читаем и выводим содержимое файла.
Запрос jQuery.ajax
Мы завернем наш ajax запрос в функцию. Вы увидите, зачем, прямо сейчас. Как вы можете видеть выше, мы использовали только три из объектов запроса jQuery ajax.
Как вы видите, затем мы перемещаем запрошенные нами данные (html) в блок #chatbox div.
Автопрокрутка
Как мы, возможно, видели в других приложениях чатов, содержимое автоматически прокручивается вниз, если контейнер лога чата (#chatbox) переполняется. Мы воплотим простую и похожую возможность, которая будет сравнивать высоту полосы прокрутки контейнера до и после того, как мы выполним ajax запрос. Если высота полосы прокрутки стала больше после запроса, мы используем эффект анимации jQuery, чтобы прокрутить блок #chatbox div.
Постоянное обновление лога чата
Теперь может возникнуть вопрос, как часто мы будем обновлять новые данные, переданные между пользователями. Или перефразируя вопрос, с какой регулярностью мы будем отправлять постоянные запросы на обновление данных?
Ответ на наш вопрос находится в функции setInterval. Эта функция будет запускать нашу функцию loadLog() каждые 2,5 секунды, которая будет запрашивать обновленный файл и делать автопрокрутку блока.

Закончили
Ниже привожу несколько ссылок, которые вы возможно захотите посмотреть, если задумаетесь о расширении этого приложения чата:
Пишем онлайн чат на Websockets используя Swoole
Тема Websocket`ов уже не раз затрагивалась на Хабре, в частности рассматривались варианты реализации на PHP. Однако, с момента выхода последней статьи с обзором разных технологий прошло уже более года, а миру PHP есть чем похвастаться за прошедшее время.
В данной статье я хочу представить русскоязычному сообществу Swoole — Асинхронный Open Source фреймворк для PHP, написанный на Си, и поставляемый в виде pecl-расширения.
Почему Swoole?
Наверняка найдутся люди, которые будут в принципе против использования PHP для таких целей, однако в пользу PHP часто могут играть:
Приступим к использованию
Ниже я опишу процесс написания несложного Websocket сервера для онлайн-чата и возможные при этом затруднения.
Перед тем как начать: Более подробная информация о классах swoole_websocket_server и swoole_server (Второй класс наследуется от первого).
Исходники самого чата.
#!/bin/bash
pecl install swoole
# get a list of avaiable packages
brew install swoole
#!/bin/bash
brew install homebrew/php/php71-swoole
Для использования автокомплита в IDE предлагается использовать ide-helper
Минимальный шаблон Websocket-сервера:
$fd — идентификатор подключения.
Получить текущие подключения:
Данные клиенту отправляются с помощью функции
Подробнее про фреймы и opcodes на русском — на learn.javascript. Раздел «формат данных»
Максимально подробно про протокол Websocket — RFC
А как сохранять данные пришедшие на сервер?
Swoole представляет функционал для асинхронной работы с MySQL, Redis, файловый ввод-вывод
А также swoole_buffer, swoole_channel и swoole_table
Думаю различия понять не сложно по документации. Для хранения имён пользователей я выбрал swoole_table. Сами сообщения хранятся в MySQL.
Итак, инициализация таблицы имён пользователей:
Заполнение данными происходит так:
Для работы с MySQL я решил пока не использовать асинхронную модель, а обращаться стандартным способом, из вебсокет-сервера, через PDO
Websocket сервер было решено оформить в виде класса, и стартовать его в конструкторе:
В обоих случая нужна реализация функции «пинг», которая будет постоянно каждые n секунд пинговать клиента в первом случае, и базу MySQL во втором.
Так как обе функции должны работать асинхронно, их нужно вызвать в дочерних процессах сервера.
Далее я реализовал простенькую функцию для пинга MySQL сервера каждые N секунд, используя swoole\Timer:
Сам таймер запускается в initPdo если ещё не включен:
Основная часть работы заключалась в написании логики для добавления, сохранения, отправки сообщений(не сложнее обычного CRUD), а далее огромный простор для усовершенствований.
Пока что я привёл свой код к более-менее читаемому виду и объектно-ориентированному стилю, реализовал немного функционала:
P.S.: Да, проверка идёт по connection id. Возможно имеет смысл заменить его в данном случае, например, на IP адрес пользователя.
Ещё я не уверен что в данной ситуации лучше всего подходил именно swoole_channel. Думаю позже пересмотреть этот момент.
— Простенькую защиту от XSS используя ezyang/htmlpurifier
С возможностью в дальнейшем добавить дополнительные проверки.
Frontend у чата пока что весьма сырой, т.к. меня больше привлекает backend, но когда будет больше времени я постараюсь сделать его поприятнее.
Где брать информацию, узнавать новости о фреймворке?
Резюме
Мне кажется, что Swoole очень активно развивался последний год, вышел из стадии когда его можно было назвать «сырым», и теперь вполне составляет конкуренцию использованию node.js/go с точки зрения асинхронного программирования и реализации сетевых протоколов.
Буду рад услышать различные мнения по теме и отзывы от тех кто уже имеет опыт использования Swoole
Пообщаться в описанном чатике можно по ссылке
Исходники доступны на Github.










