Всем привет. Сегодня я вам покажу, как сделать чат, который будет обновляться в режиме реального времени на PHP и JavaScript без AJAX и прочих дополнений. Только чистый JS и PHP, всё, как я люблю 😁
Начинаем
1. Создаём чат
У меня есть вот такой сайт, где я уже заранее сделал регистрацию, авторизацию, вёрстку чата, а также базу данных, где будут храниться данные о пользователях и сообщениях в чате.
Для начала нужно реализовать загрузку сообщений из базы данных в чат. Пишем PHP код, который будет получать все эти записи и через цикл их выводить в виде HTML кода
Создаём цикл и в него переносим код сообщения
Пока получается это
В этот код вставим переменные, полученные из записей базы данных. Для начала вставим текст сообщений
Дальше нам нужно вставить имя пользователя, но тут не всё так просто. Мы подключаемся к таблице с информацией о сообщениях, в которой есть только такие данные:
Мы можем посмотреть только id пользователя. А нам нужно по этому id получить его имя
Это можно сделать через SQL запрос. Только не пугайтесь, запрос получается вот таким вот длинным. Но если захотеть, разобраться можно
Этот запрос берёт нашу обычную таблицу "chat" и объединяет её с таблицей "user". Но не просто объединяет, этот запрос добавляет колонку "username", где id пользователей в двух таблицах совпадают. Если коротко, по таблице "user" запрос подставляет им username.
Получается это так.
Но я бы не только взял username, я бы ещё взял бы параметр textname
После того, как мы попробовали SQL запрос в базе данных, можно применять его и в нашем коде
Вот, замечательно. Уже что-то адекватное
Теперь надо сделать так, чтобы сообщения можно было отправлять
Нужно создать PHP файл, через который мы будем отправлять данные из этой формочки на сервер
Пишем код. Отправляем данные на сервер и возвращаемся обратно в chat.php
Наш чат уже заработал, но, чтобы отправить сообщение, нужно нажать на кнопку в форме, которая перекидывает вас на другую страницу, быстро выполняет код и возвращает в чат. Происходит это быстро, но страница всё равно обновляется.
Если сообщения не отправлять, а читать, то страница сама по себе обновляться не будет, и в чате останутся старые сообщения. Чтобы читать новые, нужно постоянно обновлять страницу, что очень неудобно.
Именно для этого я и пишу эту статью, чтобы показать, как сделать подгрузку сообщений в режиме реального времени.
Лично я, когда был новичком в этом деле, пытался эту проблему решить, и когда я искал способы, постоянно натыкался на ответы, где люди писали про AJAX. Мне очень хотелось написать код без использования сторонних ресурсов, только на чистом JS и PHP, это можно легко реализовать, о чём я напишу в следующем заголовке
В чате есть небольшая проблема, при загрузке страницы, он пролистывается в самое начало, а должен быть пролистнут в самый конец.
Чтобы это исправить, пишем вот такой код
Этот код, после загрузки DOM дерева (это нужно, чтобы он применялся, когда чат полностью загрузится) задаёт прокрутку чата и прокручивает в самый низ.
2. Обновление сообщений в режиме реального времени
Теперь нам нужно сделать обновление сообщений в режиме реального времени.
Объясняю. Нам нужно сделать код, который после первой загрузки наших сообщений при открытии чата, будет сравнивать, не появились ли в базе данных сообщения с датой, которая наступила позже, чем последнее наше обновление чата. После чего мы должны будем загрузить эти сообщения и добавить их в HTML.
Можно было бы сделать это проще и просто сделать код, который каждый раз перезагружал все эти сообщения заново, но так делать будет не разумно, каждый раз обращаться к базе данных и менять HTML разметку это лишняя нагрузка на сервер и устройство пользователя. Поэтому делать будем по-умному.
В SQL запросе можно сравнивать даты так. Когда я первый раз узнал, то был очень удивлён
Пишем скрипт на JS. Создаём переменную, куда после загрузки страницы записываем время последнего обновления чата (в миллисекундах) (1773933612266)
Создадим функцию load_chat, которая будет выполняться каждую секунду. Эта функция будет отправлять запрос в файл loadchat.php, который будет уже связываться с базой данных
Так... Что мы делаем дальше? Подготовьтесь, возможно, будет немного сложно, если у вас плохо с JavaScript
Через fetch мы отправляем запрос в файл loadchat.php, но теперь в коде появились изменения, что я сделал?
Я сделал так, чтобы мы могли передавать параметры в файл loadchat.php. Я создал объект URLSearchParams, через который можно передавать параметры так, как будто мы их отправили через форму HTML, там можно использовать GET и POST методы. В этот объект я добавил параметр time, в который записал значение времени. После чего я обновил fetch запрос, добавил туда body, который содержит эти параметры, и информацию о методе передаче (POST).
Метод fetch срабатывает не сразу, должно пройти какое-то время, возможно незначительное. Мы не может просто вызвать этот метод и сразу вытащить из него результат, нужно на это время. Поэтому наш код сначала попытается сделать запрос, потом попытается из пустого результата вытащить данные, а уже потом выполнится сам запрос. Чтобы это исправить, я сделал нашу функцию асинхронной (async) и добавил await перед fetch, await будет заставлять наш код ждать результаты этой функции. Await работает только в асинхронной функции, если интересно, поизучайте дополнительно.
Внутри PHP мы можем получать наши значения, и делается это довольно просто, как в формах.
В нашей таблице время выглядит вот так
Нужно преобразовать миллисекунды в это
Создаём объект DateTime, потом туда закладываем наше время. Просто время в миллисекундах туда положить нельзя, нужно в секундах, поэтому делим на 1000 и округляем.
Теперь подключаемся к нашей базе данных. Через запрос получим сообщения, которые были отправлены после нашего обновления, и посчитаем их
Результаты подсчёта мы выведем на экран.
В самом JS мы получим результат отправки запроса в loadchat.php, преобразуем в текст и выведем в консоль
Чтобы проверить наш код, откроем вторую вкладку, набросаем туда сообщений и посмотрим, что выведет наш код
Наш код показывает, что новых сообщения у нас два.
Теперь сделаем загрузку самих сообщений.
Дальше даже не знаю. Как бы вам это всё понятнее объяснить.
Мы меняем цикл со счётчиком на цикл, который будет генерировать HTML код новых сообщений и сохранять его в переменную html. При этом важно не забывать, что чтобы через запрос получить не только id автора сообщения, но и его ник, нужен более сложный запрос. Я уже показывал, как это написать, можете вернуться, пролистать статью наверх и посмотреть. Только к этому запросу мы добавляем условие `date` > '$time'.
В итоге получается запрос, который выводит таблицу с новыми сообщениями + ником автора (ника автора в таблице "chat" нет, только его id)
И так, надеюсь, вам было понятно... охх...
Этот самый цикл мы выводим и получаем через JS.
А вот здесь ещё один интересный момент. Теперь мы наш HTML код должны вставить в нашу разметку
Я решил вынести переменную chat за функцию для удобства.
После нашего запроса и получения HTML кода, мы должны правильно вставить его в разметку. Если мы напрямую используем innerHTML, чтобы вставить HTML код, то наш элемент чата будет криво обновляться. Его разметка будет переделываться и могут возникнуть трудности, например, нельзя будет выделять сообщения, каждую секунду чат будет обновляться и переделывать свою HTML разметку, выделение будет сбиваться.
Поэтому мы сделаем так. Мы создадим через createElement новый элемент и запишем его в messages. После чего применим innerHTML к отдельному элементу и загрузим сообщения. После чего через appendClild мы аккуратненько загрузим этот элемент в чат, и не будет никаких багов, вроде.
Также не забываем менять переменную time и сбрасывать таймер.
Ну а также после обновления не забываем прокручивать чат вниз.
Я открыл две вкладки и попробовал отправить сообщение в одном чате, а принять в другом, работает!!
А теперь финальный штрих
3. Делаем отправку сообщений без обновления страницы
Сделать отправку сообщений можно по тому же принципу, что и их загрузку.
Пишем вот такой удивительный код. Мы подключаемся к нашей форме, получаем событие отправки данных и через функцию preventDefault() отправку данных отменяем. Вместо этого мы можем добавить свои функции.
Также создаём объект URLSearchParams, загружаем в него значение элемента textarea и отправляем его так, как будто мы это отправили из той же формы. Только очистить элемент textarea не забудьте
И получается вот так
Наш чат начал работать, ура!!
Подводим итоги
Мы сделали чат, который обновляется в режиме реального времени, а также отправляет сообщения без перезагрузки, и сделали всё это на чистом PHP и JavaScript.
Я показал вам самую базу, самые основы, как это сделать. Я прекрасно понимаю, что этот чат можно сделать лучше, можно оптимизировать некоторые процессы и добавить функции. Ту же функцию удаления сообщений можно добавить. Если у вас есть своё мнение - прекрасно, если вы эксперт, который разбирается в этой теме лучше, можете поделиться этим в комментариях, любая разумная критика приветствуется.
Этому чату далеко до совершенства и до современных чатов, но я вам показал основу, как в целом такое реализовать, чтобы сообщения отображались и отправлялись в режиме реального времени без перезагрузки страницы.
Ну а я надеюсь, что вы оцените, поставите лайк, оставите комментарий, а может быть даже и подпишитесь))