Создания простого чата
Для начала создадим простой чат с помощью HTML&CSS и PHP&MySQL
Проектирование Базы Данных
- Переходим к phpMyAdmin.
- Создаем новую базу данных, называем “chatdb”.
- Создаем новую таблицу, называя “Posts”, включая в себя 4 столбца:
- “id” тип колонки INT, автоматическое увеличение на 1 (задаем A_I в ячейку с флажком) основной ключ (index);
- “nick” тип колонки VARCHAR и длина 100;
- “post_text” тип колонки TEXT;
- “post_dt” тип колонки DATETIME по умолчанию является CURRENT_TIMESTAMP.
Создание веб-сайта.
- Во-первых, создадим главную страницу. Список комментариев и отправка формы, используя кнопку. Всё будет находится в файле “index.php” . Давайте создадим этот файл и напишем что-то вроде этого:
<html>
<head>
head>
<body>
php
$mysqli = new mysqli("127.0.0.1", "root", "", "chatdb");
/* "127.0.0.1" is MySQL host name. In local servers (XAMPP, Ampps, etc.) it is 127.0.0.1. If you using a dedicated hosting, see it in admin panel. */
/* "root" and "" is login and password for DB's user. In local servers usually default DB user is "root" with empty password. */
/* "chatdb" is DB's name. */
/* Warning: in XAMPP you should manually run MySQL server (from xampp-control.exe) to get it work. */
$result = $mysqli->query("SELECT * FROM posts;");
?>
<style>
/* All CSS is very simplified. I provide it for example and no more.
* In Chrome it works tolerably, but in IE and Firefox it works very poorly.
*/
.content {
display: table;
width: 50%;
min-width: 400px;
height: 80%;
/* Center horizontally and vertically */
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
margin: auto;
/* Design */
border: 1px solid;
background-color: silver;
padding: 5px;
}
/* For mobile devices */
@media (max-width: 400px) {
.content {
width: 100%;
min-width: 0;
padding: 0px;
}
}
style>
<div class="content">
<div id="comments" style="overflow-y: scroll; height: 100%;">
php
if ($result) {
while ($post = $result->fetch_object()){
$nick = $post->nick;
$post_dt = $post->post_dt;
$post_text = $post->post_text;
echo "<b>$nickb> ($post_dt):<br>";
echo "$post_text<br>";
echo "<br>";
}
$result->close();
}
?>
div>
php
$mysqli->close();
?>
<form action="post.php" method="post" style="height: 0; display: table-row;">
Nick:<br>
<input type="text" name="nick" style="width: 100%;">input><br>
<br>
Text:<br>
<textarea name="text" style="width: 100%;">textarea><br>
<br>
<input type="submit">input>
form>
div>
<script type="text/javascript">
var divComments = document.getElementById('comments');
divComments.scrollTop = divComments.scrollHeight;
script>
body>
html>
2. Дальше давайте создадим “post.php” файл и напишем такое:
php
$nick = $_POST['nick'];
$post_text = $_POST['text'];
$mysqli = new mysqli("127.0.0.1", "root", "", "chatdb");
$nick = $mysqli->real_escape_string($nick);
$nick = htmlspecialchars($nick);
$post_text = $mysqli->real_escape_string($post_text);
$post_text = htmlspecialchars($post_text);
$mysqli->query("INSERT INTO posts (nick, post_text) VALUES ('$nick', '$post_text');");
$mysqli->close();
/* Redirect To Main Page */
header('Location: ' . $_SERVER['HTTP_REFERER']);
?>
3. Откроем ваш чат в любом продвинутом браузере. Вся работа:
4. Напишите ник и текст, а потом нажмите на кнопку отправки.
Когда отправили форму, сразу же происходит перенаправление формы главной страницы в “post.php”. “Post.php” моментально наполняет данными таблицу и перенаправляет на главную страницу. Также “post.php” содержит начальный XSS и SQL защищенный вход. Для упрощения не отправляем клиентам время с JS на “post_dt” на внесения данных, а указываем значение по умолчанию – CURRENT_TIMESTAMP, который предоставляет нынешнюю дату и время на сервер.
Когда количество комментариев больше, чем экран может вместить, то комментарии переполнены в div, используется вертикальный скроллбар. Во время загрузки страницы JS автоматически опускает скроллбар вниз к недавнему комментарию.
Что тут не так?
Проблема номер 1. Новый непрочитанный комментарий от пользователя не загружается в базу данных автоматически, без ручной перезагрузки страницы.
Это очень, очень серьезная проблема для любого чата.
Как это исправить?
Очевидно, один из путей сделать это - использовать HTTP-запрос к фоновой работе автоматически (с помощью JS) и асинхронно, то есть это один из способов обеспечить выполнение AJAX в любой form.
Проблема номер 2. Также неправильно то, что кнопка отправки перезагружает страницу (перенаправляет на вторую страницу и следующим шагом возвращает назад).
При перезагрузке страницы сбрасывает “Nick” в поле (также, как любые другие изменения, те, что сделали с пользователем)
Как это исправить?
Конечно, можно обеспечить выполнение обхода для сохранения изменений и перезагрузки на перезагружаемой странице. Но не эффективнее ли устранить причину, чем последствие? Можно только убрать перезагружаемую страницу и эта проблема будет решена автоматически.
Проблема номер 2.1. Видите ли что-то необычное тут?
Это слишком быстро?
Дело с чатом очень простое – загружаем только два маленьких текстовых параметра. Что делать, если нужно улучшить чат с помощью добавления присоединения, а конкретно - изображений и видео? Видео может иметь объем в размере нескольких мегабайт, что тогда в этом случае?
Давайте попробуем. Давайте немного изменим “post.php”, после $mysql->query() добавив это:
for ($i = 0; $i < 1000000000; $i++) { }
Старайтесь размещать какие-либо комментарии. Что мы видим? Нет, UI не остановилось (заморозилось), но браузер ждет до того, как закончится подключение:
Да, если “post.php” вызывает какую-то необработанную ошибку, то чат исчезает, и пользователь видит пустое окно с сообщением о непонятной ошибке. Чтобы вернуться к чату, пользователю стоит нажать кнопку “Back” в браузере. И это проблема номер 2.2.
Давайте уберем петлю с “post.php” и исправим эти проблемы.
Реализация легкого AJAX в простой чат
Автоматическое обновление комментариев
Эта веб-страница без AJAX? Это веб-страница, которая полностью перезагружается.
Эта веб-страница c AJAX? Это веб-страница, что перезагружается частично.
Где же взять части этих страниц? Стоит разделить нашу страницу на части, в этом случае сервер генерирует страницу частично.
Страница будет состоять из двух частей – блок комментариев и другой контент страницы. Комментарии будут загружаться и перезагружаться отдельно от другой страницы.
Давайте сделаем первую часть, то есть блок комментариев.
Для начала создадим пустой файл, назовем “getcomment.php”.
Дальше переходим в “index.php” для того, чтобы вырезать комментарии и далее отделить его.
1. Вырезаем инициализированный блок MySQL с “index.php"
php
$mysqli = new mysqli("127.0.0.1", "root", "", "chatdb");
/* "127.0.0.1" is MySQL host name. In local servers (XAMPP, Ampps, etc.) it is 127.0.0.1. If you using a dedicated hosting, see it in admin panel. */
/* "root" and "" is login and password for DB's user. In local servers usually default DB user is "root" with empty password. */
/* "chatdb" is DB's name. */
/* Warning: in XAMPP you should manually run MySQL server (from xampp-control.exe) to get it work. */
$result = $mysqli->query("SELECT * FROM posts;");
?>
вставляем в “getcomments.php”.
2. Следующее, вырежем контент div c комментариями с “index.php”:
php
if ($result) {
while ($post = $result->fetch_object()){
$nick = $post->nick;
$post_dt = $post->post_dt;
$post_text = $post->post_text;
echo "<b>$nickb> ($post_dt):<br>";
echo "$post_text<br>";
echo "<br>";
}
$result->close();
}
?>
И вставим (добавим) в “getcomments.php” после инициализации MySQL.
3. Дальше, вырежем недалекий блок MySQL с “index.php”:
php
$mysqli->close();
?>
Вставим его в конец файла “getcomments.php”.
4. Наконец-то, убираем JS-скрипт, который опускает скролл в самый низ.
<script type="text/javascript">
var comments = document.getElementById('comments');
comments.scrollTop = comments.scrollHeight;
script>
Не переживай, это только временно.
5. Сделано. Теперь имеем что-то наподобие этого:
<html>
<head>
head>
<body>
<style>
/* All CSS is very simplified. I provide it for example and no more.
* In Chrome it works tolerably, but in IE and Firefox it works very poorly.
*/
.content {
display: table;
width: 50%;
min-width: 400px;
height: 80%;
/* Center horizontally and vertically */
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
margin: auto;
/* Design */
border: 1px solid;
background-color: silver;
padding: 5px;
}
/* For mobile devices */
@media (max-width: 400px) {
.content {
width: 100%;
min-width: 0;
padding: 0px;
}
}
style>
<div class="content">
<div id="comments" style="overflow-y: scroll; height: 100%;">
div>
<form action="post.php" method="post" style="height: 0; display: table-row;">
Nick:<br>
<input type="text" name="nick" style="width: 100%;">input><br>
<br>
Text:<br>
<textarea name="text" style="width: 100%;">textarea><br>
<br>
<input value="Submit" type="submit">input>
form>
div>
body>
html>
getcomments.php:
php
$mysqli = new mysqli("127.0.0.1", "root", "", "chatdb");
/* "127.0.0.1" is MySQL host name. In local servers (XAMPP, Ampps, etc.) it is 127.0.0.1. If you using a dedicated hosting, see it in admin panel. */
/* "root" and "" is login and password for DB's user. In local servers usually default DB user is "root" with empty password. */
/* "chatdb" is DB's name. */
/* Warning: in XAMPP you should manually run MySQL server (from xampp-control.exe) to get it work. */
$result = $mysqli->query("SELECT * FROM posts;");
?>
Вероятно, теперь наша страница разделена.
Давайте проверим её. Переходим http (точнее ССЫЛКА для локального сервера).
Дальше, переходим на главную страницу, http:///index.php
Это удивительно! Всё удачно получилось, разделив страницу на части за пару минут!
Не останавливаемся на этом. Теперь “glue” эти части с помощью AJAX. Как это сделать?
1. Для начала стоит создать пустой JS-скрипт на главной странице:
<script type="text/javascript">
alert('Test');
script>
Добавив это после тега div, перед закрывающимся тегом .
2. Сделаем HTTP GET запрос от JS к “getcommet.php”
Для этого используем XMLHtttpRequest (XHR) класс:
<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.open('GET', '/getcomments.php', false);
xhr.send(null);
if (xhr.status == 200) {
alert(xhr.responseText);
}
script>
Это работает, но не читает старые версии IE те, что не поддерживают такую инициализацию.
Для получения более кросс-браузерного пути переходим в
и добавляем это:
<script type="text/javascript">
function getXmlHttp(){
var xmlhttp;
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
xmlhttp = new XMLHttpRequest();
}
return xmlhttp;
};
script>
И главный скрипт (в конце)
<script type="text/javascript">
var xhr = getXmlHttp();
xhr.open('GET', '/getcomments.php', false);
xhr.send(null);
if (xhr.status == 200) {
alert(xhr.responseText);
}
script>
Как видно, теперь JS получает контент со страницы “getcomments.php” и показывает это в предупреждении.
2.1. Вопрос: «Это на самом деле AJAX (Asynchronous Javascript And Xml)?»
Это AJAX, потому что запрос сервера отформатирован в HTML (который основан на XML).
Но действительно ли это AJAX, это асинхронно?
Проверим. Добавим эти уже знакомые строки в любое место между в “getcomments.php”:
for ($i = 0; $i < 1000000000; $i++) { }
Что теперь видно на загружаемой странице?
Вначале страница зависает, его замораживает UI (становится не реагирующим на нажатие левой/правой кнопки мыши):
Дальше Chrome показывает навязчивое всплывающие окно, сообщающее об удалении страницы:
Это не AJAX! Это JAX! Как его сделать асинхронным?
К счастью, ХHR также поддерживает асинхронный режим:
<script type="text/javascript">
var xhr = getXmlHttp();
xhr.open('GET', '/getcomments.php', true); /* true for asynchronous */
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if(xhr.status == 200) {
alert(xhr.responseText);
}
}
};
xhr.send(null);
script>
В этом случае браузер не ждет ответа с главного потока пользовательского интерфейса, он запускает в другом (асинхронно) и вызываемым событием “onreadystatechange” в главном контексте UI.
Теперь всё в порядке, страница полностью доступна, пока запрос запущен, и после ответа получит предупреждение.
for ($i = 0; $i < 1000000000; $i++) { }
И продолжаем работу.
3. Добавляем этот контент в div вместо предупреждения. Заменить это:
alert(xhr.responseText);
C этим:
var divComments = document.getElementById('comments');
divComments.innerHTML = xhr.responseText;
Возвращаем назад, клиент видит “glued” страницу с блоком комментариев.
4. Дальше следует установить интервал для автоматической проверки новых комментариев время от времени… и также восстановить удаленный сценарий автоматической прокрутки.
Відео курси за схожою тематикою:
<html>
<head>
<script type="text/javascript">
function getXmlHttp() {
var xmlhttp;
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
xmlhttp = new XMLHttpRequest();
}
return xmlhttp;
};
script>
head>
<body>
<style>
/* All CSS is very simplified. I provide it for example and no more.
* In Chrome it works tolerably, but in IE and Firefox it works very poorly.
*/
.content {
display: table;
width: 50%;
min-width: 400px;
height: 80%;
/* Center horizontally and vertically */
position: absolute;
left: 0; right: 0;
top: 0; bottom: 0;
margin: auto;
/* Design */
border: 1px solid;
background-color: silver;
padding: 5px;
}
/* For mobile devices */
@media (max-width: 400px) {
.content {
width: 100%;
min-width: 0;
padding: 0px;
}
}
style>
<div class="content">
<div id="comments" style="overflow-y: scroll; height: 100%;">
div>
<form action="post.php" method="post" style="height: 0; display: table-row;">
Nick:<br>
<input type="text" name="nick" style="width: 100%;">input><br>
<br>
Text:<br>
<textarea name="text" style="width: 100%;">textarea><br>
<br>
<input value="Submit" type="submit">input>
form>
div>
<script type="text/javascript">
var divComments = document.getElementById('comments');
function loadComments() {
var xhr = getXmlHttp();
xhr.open('GET', '/getcomments.php', true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
if (xhr.responseText !== divComments.innerHTML) {
divComments.innerHTML = xhr.responseText;
divComments.scrollTop = divComments.scrollHeight;
}
}
}
};
xhr.send(null);
};
loadComments();
setInterval(loadComments, 1000)
script>
body>
html>
Теперь проблема исправить это. Новые комментарии с другого пользовательского чата (другие вкладки браузеров, окон и экземпляров) получают каждые 1000 миллисекунды (1 секунду) автоматически.
Но отправка комментариев уже вызывает перезагрузку нашей страницы.
Отправка комментариев без перезагрузки
Как написано выше, XHR помогает отправлять HTTP GET-запросы без перезагрузки страницы и GUI заморозки (асинхронно).
Теперь отправляем HTTP-запрос асинхронно, но на этот раз POST запрос, а не GET.
И, естественно, XHR позволяет это. Используем метод send(). Для GET указываем null. Для POST устанавливаем запрос “body”.Также нужно добавить “Content-Type:application/x-www-from-urlencoded” в header для того, чтобы разрешить серверу знать, какой формат использовать для отправки данных.
Заметка: если не знаете, что отправлять, то можно захватить регулярный запрос с помощью “Fiddler” или же любой другой HTTP-перехватчик и только просимулировать запрос. HTTP-перехватчик — это незаменимый инструмент для работы с HTTP/HTTPS. Это позволяет увидеть все headers и bodies по всем HTTP(S)-запросам, что отправляются в систему. Лучше использовать “Fiddler”, это бесплатное, современное и очень простое приложение, что может поддерживать HTTP/HTTPS и оба Win x86/x64.
1. Для начала создадим пустой JS скрипт в HTML. Разместить до самого
Статті за схожою тематикою