In this Tutorial, I’ll show you how you can write your very own web-based Chat App using HTML, CSS, JavaScript/jQuery, PHP and MySQL.








For a full functioning Web-Chat we’ll need three basic components:
- A Client-Side HTML Document that sends the Chat Text and receives Data from the database
- A PHP file which writes user input into the database
- A database (we’ll use MySQL in this Example) to save and manage the messages
So let’s start by creating our Front End.
The User Interface
Let’s start by creating a basic HTML template with jquery and some pretty standard code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>rChat</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css" type="text/css" media="screen" /> <link rel="stylesheet" href="css/main.css" type="text/css" media="screen" /> </head> <body> <div class="container"> <header class="header"> <h1>rChat</h1> </header> <main> <!-- Our app will go here--> </main> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src="js/rChat.js"></script> </body> </html> |
Most Chat Apps consist of a basic form with an output field to show the messages, an input field for our user to write into, optionally an input field for the username and last but not least a button to send the message.
1 2 3 4 5 6 7 8 9 |
<div class="userSettings"> <label for="userName">Username:</label> <input id="userName" type="text" placeholder="Username" maxlength="32" value="Somebody"> </div> <div class="chat"> <div id="chatOutput"></div> <input id="chatInput" type="text" placeholder="Input Text here" maxlength="128"> <button id="chatSend">Send</button> </div> |
So our whole html now looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>rChat</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css" type="text/css" media="screen" /> <link rel="stylesheet" href="css/main.css" type="text/css" media="screen" /> </head> <body> <div class="container"> <header class="header"> <h1>rChat</h1> </header> <main> <div class="userSettings"> <label for="userName">Username:</label> <input id="userName" type="text" placeholder="Username" maxlength="32" value="Somebody"> </div> <div class="chat"> <div id="chatOutput"></div> <input id="chatInput" type="text" placeholder="Input Text here" maxlength="128"> <button id="chatSend">Send</button> </div> </main> </div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src="js/rChat.js"></script> </body> </html> |
Of course, our chat doesn’t look like a chat at the moment, but hey, that’s what CSS is for right? so let’s style it a bit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
/*Border-box reset*/ html { box-sizing: border-box; } *, *:before, *:after { box-sizing: inherit; } /*Chat styling*/ body { display: flex; justify-content: center; align-items: center; } .userSettings { margin-bottom: 20px; } .chat { max-width: 400px; display: flex; flex-direction: row; flex-wrap: wrap; } .chat #chatOutput { overflow-y: scroll; height: 280px; width: 100%; border: 1px solid #777; } .chat #chatOutput p { margin: 0; padding: 5px; border-bottom: 1px solid #bbb; word-break: break-all; } .chat #chatInput { width: 75%; } .chat #chatSend { width: 25%; } |
Now that looks better. Feel free to style it even more.
Scripts
Our chat doesn’t really do anything right now, so let’s look into that. First up we’ll setup jQuery’s ready()
and store the important elements into variables:
1 2 3 4 5 6 |
$(document).ready(function() { var $userName = $("#userName"); var $chatOutput = $("#chatOutput"); var $chatInput = $("#chatInput"); var $chatSend = $("#chatSend"); }); |
So here is what we want to do: Whenever the “Send” Button is pressed, we want our script to send the chat input to the server. Also we need an interval that regularly checks for new chat messages from the server to display.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
$(document).ready(function() { var chatInterval = 250; //refresh interval in ms var $userName = $("#userName"); var $chatOutput = $("#chatOutput"); var $chatInput = $("#chatInput"); var $chatSend = $("#chatSend"); $chatSend.click(function() { sendMessage(); }); setInterval(function() { retrieveMessages(); }, chatInterval); }); |
Now we need to define what sendMessage()
and retrieveMessages()
will do:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
$(document).ready(function() { var chatInterval = 250; //refresh interval in ms var $userName = $("#userName"); var $chatOutput = $("#chatOutput"); var $chatInput = $("#chatInput"); var $chatSend = $("#chatSend"); function sendMessage() { var userNameString = $userName.val(); var chatInputString = $chatInput.val(); $.get("./write.php", { username: userNameString, text: chatInputString }); $userName.val(""); retrieveMessages(); } function retrieveMessages() { $.get("./read.php", function(data) { $chatOutput.html(data); //Paste content into chat output }); } $chatSend.click(function() { sendMessage(); }); setInterval(function() { retrieveMessages(); }, chatInterval); }); |
Now we send the content of both the username and the chat-input to the write.php
via GET. retrieveMessages
on the other hand loads the content of read.php
into the chat-output.
Writing into the Database
In our “write.php” we’ll want to to our database, to which we must connect first. We supply the login-data from a file called _connect.php
.
write.php:
1 2 3 4 5 6 7 8 9 10 11 |
<?php require("./_connect.php"); //connect to db $db = new mysqli($db_host,$db_user, $db_password, $db_name); if ($db->connect_errno) { //if the connection to the db failed echo "Failed to connect to MySQL: (" . $db->connect_errno . ") " . $db->connect_error; } ?> |
_connect.php:
1 2 3 4 5 6 7 8 |
<?php //Enter the connection details of your MySQL database here $db_host="localhost"; $db_user="root"; $db_password=""; $db_name="chatapp"; ?> |
We receive the user input from the URL so we can access them with “$_GET[”]”. Limiting the maximal length of the input makes sure users dont paste huge strings into our db.
Make sure to use mysqli\_escape\_string
and htmlentities
to escape the user input! Otherwise, your chat is vulnerable to SQL-Injections!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<?php require("./_connect.php"); //connect to db $db = new mysqli($db_host,$db_user, $db_password, $db_name); if ($db->connect_errno) { //if the connection to the db failed echo "Failed to connect to MySQL: (" . $db->connect_errno . ") " . $db->connect_error; } //get user-input from url $username=substr($_GET["username"], 0, 32); $text=substr($_GET["text"], 0, 128); //escaping is extremely important to avoid injections! $nameEscaped = htmlentities(mysqli_real_escape_string($db,$username)); //escape username and limit it to 32 chars $textEscaped = htmlentities(mysqli_real_escape_string($db, $text)); //escape text and limit it to 128 chars ?> |
Now we are ready to write the user input into the Database. This can be done by sending a MySQL query to the database containing our data. We want the server to show an error when it doesn’t work, and to show the a success message if it succeeds.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<?php require("./_connect.php"); //connect to db $db = new mysqli($db_host,$db_user, $db_password, $db_name); if ($db->connect_errno) { //if the connection to the db failed echo "Failed to connect to MySQL: (" . $db->connect_errno . ") " . $db->connect_error; } //get user-input from url $username=substr($_GET["username"], 0, 32); $text=substr($_GET["text"], 0, 128); //escaping is extremely important to avoid injections! $nameEscaped = htmlentities(mysqli_real_escape_string($db,$username)); //escape username and limit it to 32 chars $textEscaped = htmlentities(mysqli_real_escape_string($db, $text)); //escape text and limit it to 128 chars //create query $query="INSERT INTO chat (username, text) VALUES ('$nameEscaped', '$textEscaped')"; //execute query if ($db->real_query($query)) { //If the query was successful echo "Wrote message to db"; }else{ //If the query was NOT successful echo "An error occurred"; echo $db->errno; } $db->close(); ?> |
The Database
As we haven’t created our table already we will now do this. Our table is pretty simple: one column for the time, text and name each plus an id column which increases by itself every time something gets written, while being our index. The easiest way to achieve this is to enter the following MySQL code in the SQL tab of your PhpMyAdmin:
1 2 3 4 5 6 7 |
CREATE TABLE IF NOT EXISTS `chat` ( `id` int(11) NOT NULL AUTO_INCREMENT, `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `username` varchar(32) NOT NULL, `text` varchar(128) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 |
Now our chat is able to store the input the user enters on our chat site, but we don’t see it on the chat HTMl site. Time to change this!
Reading the Database
the fact that PHP only gets executed when the user request the page makes us unable to simply include the data of the database into our chat site. A way to work around this is having a separate file like “read.php” where we will do this. Later we will load the contents of this site dynamically trough jQuery.
Our “read.php” looks something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<?php require("./_connect.php"); //connect to db $db = new mysqli($db_host,$db_user, $db_password, $db_name); if ($db->connect_errno) { //if the connection to the db failed echo "Failed to connect to MySQL: (" . $db->connect_errno . ") " . $db->connect_error; } $query="SELECT * FROM chat ORDER BY id ASC"; //execute query if ($db->real_query($query)) { //If the query was successful $res = $db->use_result(); while ($row = $res->fetch_assoc()) { $username=$row["username"]; $text=$row["text"]; $time=date('G:i', strtotime($row["time"])); //outputs date as # #Hour#:#Minute# echo "<p>$time | $username: $text</p>\n"; } }else{ //If the query was NOT successful echo "An error occured"; echo $db->errno; } $db->close(); ?> |
What we do here is similar to write.php
, however in this case we want to read from the database, so we use SELECT in our query. We then loop over every entry and echo a p
html tag with its contents. Also we need to format the date, we dont need the whole timestamp.
Done! Now our chat will update itself every 250 milliseconds.
wow! you’ve broken down the information with great easy to follow pictures that even a blogging novice like me can follow along! Super accessible. Great job! Thanks for sharing your knowledge
Thank you for giving such a detailed explanation. Technical things often scare me, but you have given such a good explanation.
Thank you for share about this script. But there are some question for you
1. Can you impress your reader that your script will work when it go online, because i have been see that you just use localhost or you can say offline
2. Could you using mysql to replace mysqli ? because I have seen your script and it belong to the others webiste you should be modified it?
Wow this was really informational. It was a lot easier to follow than what I thought it would be! Even those who are not tech-savvy would be able to follow this.