Advanced Live Group Chat With WebSocket, PHP & jQuery


WebSocket is one of the awesomest part of the HTML5 and we developers should experiment with it as it will be the future of client to server communication.

In a recent post, I made a tutorial of live chat with WebSockets and PHP. It was the basic step into websockets. But, I have created another chat which is more advanced that has the capability to upload images as well as record audio from microphone of the user. It’s somewhat like WhatsApp or Facebook Messenger.

For this, you will need a WebSocket server and a web server (localhost).

Features

  • Basic text messaging
  • Anyone can join chat
  • Voice messages
  • Send images
  • Live messaging

This tutorial has two parts, one for setting up the website and the other for setting up the WebSocket server.

Website

The client doesn’t necessarily need to be PHP, because we aren’t gonna process the data here. But, since we are uploading images as well as audio, we should make files in the client site itself to upload these files.

index.php

This is the file the users would see to chat :

<!DOCTYPE html>
<html>
  <head>
    <script src="//lab.subinsb.com/projects/jquery/core/jquery-2.1.1.js"></script>
    <script src="//lab.subinsb.com/projects/Francium/voice/recorder.js"></script>
    <script src="//lab.subinsb.com/projects/Francium/voice/Fr.voice.js"></script>
    
    <script src="js/time.js"></script>
    <script src="js/chat.js"></script>
    <link href="css/chat.css" rel="stylesheet"/>
    <title>Subin's Blog - Advanced Live Group Chat</title>
  </head>
  <body>
    <div id="content">
      <center><h1>Advanced Live Group Chat</h1></center>
      <p><a href="//subinsb.com/php-websocket-advanced-chat">Tutorial</a></p>
      <div class="chatWindow">
        <div style="display: none;postion: absolute;">
          <input type="file" id="photoFile" accept="image/*" />
          <audio src="cdn/message.wav" controls="false" id="notification"></audio>
        </div>
        <div class="users"></div>
        <div class="chatbox">
          <div class="topbar">
            <span id="status" title="Click to Login/Logout">Offline</span>
            <span id="fullscreen" title="Toggle Fullscreen of Chat Box">Fullscreen</span>
          </div>
          <div class="chat">
            <div class="msgs"></div>
            <form id="msgForm">
              <textarea name="msg" placeholder="Type message here...."></textarea>
              <a class="button" id="voice" title="Click to start recording message"></a>
              <a class="button" id="photo" title="Type in a message and choose image to send"></a>
            </form>
          </div>
          <div class="login">
            <p>Type in your name to start chatting !</p>
            <form id="loginForm">
              <input type="text" value="" />
              <button>Submit</button>
            </form>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

It has a basic layout with some resources loaded in the head.

upload.php

This file handles the uploads such as images and audios. It will upload the file into a folder named “uploads” in the root directory of the site. So, you should create that folder and set the permission of it to “Read & Write”.

Here is the upload.php file :

<?php
if(isset($_FILES['file'])){
  $file = file_get_contents($_FILES['file']['tmp_name']);
  $f = finfo_open();
  $mime_type = finfo_buffer($f, $file, FILEINFO_MIME_TYPE);
  
  $supported_types = array(
    "audio/x-wav" => "wav",
    "image/png" => "png",
    "image/jpeg" => "jpg",
    "image/pjpeg" => "jpg",
    "image/gif" => "gif"
  );
  
  $extension = isset($supported_types[$mime_type]) ? $supported_types[$mime_type] : false;
  if($extension !== false){
    $fileName = rand(10000, 65000) . "." . $extension;
    $location = __DIR__ . "/uploads/" . $fileName;
    
    move_uploaded_file($_FILES['file']['tmp_name'], $location);
    echo $fileName;
  }
}

You can see that the upload file checks the type of the file and then only it uploads to the server. When it is uploaded, the file name is outputted.

js/time.js

You might have heard about the jQuery Timeago plugin. This file has the plugin with some little modifications. Download it from here.

js/chat.js

This is the heart of the chat. All functions related to the chat in the client are processed by this file such as connection to the server, sending messages, uploading files and others…

You can get this file from here.

css/chat.css

This file will decorate the chat box. We are adding just a simple design.

You can get this file from here.

assets/message.wav

There is something else too in this chat. A notification sound. When new messages are retrieved, a sound will be also played. You can download this file from here. Thanks to the open source software Pidgin IM for this sound.

assets

The “assets” folder should contain 3 images :

These files are for the advanced part of the chat. With advancement comes more resources !

WebSocket Server

Let’s move on to the WebSocket Server. This part handles the messages and does all the work to make the chat functional and awesome.

Database

The server has the Database, so create the tables first :

CREATE TABLE `wsAdvancedChat` (
  `id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
  `user` varchar(20) NOT NULL,
  `msg` varchar(100) NOT NULL,
  `type` varchar(10) NOT NULL,
  `file_name` varchar(100) NOT NULL,
  `posted` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

Make sure the database time zone is set to UTC.

Then you should create a configuration file that will provide the credentials to connect to the database :

config.php

We are going to use PDO for the connection with MySQL :

<?php
ini_set("display_errors","on");
$docRoot  = realpath(dirname(__FILE__));

if( !isset($dbh) ){
  session_start();
  date_default_timezone_set("UTC");
  $musername = "root";
  $mpassword = "password";
  $hostname  = "127.0.0.1";
  $dbname    = "test";
  $port      = "3306";

  $dbh = new PDO("mysql:dbname={$dbname};host={$hostname};port={$port}", $musername, $mpassword);
  /**
   * Change The Credentials to connect to database.
   */
}
?>

We also set the timezone to UTC which is the same for database server and PHP server.

We will use Francium DiffSocket to set up our WebSocket server. In the “server” directory, run :

composer require francium/diffsocket

Once DiffSocket is installed, we should set up the server class and the script to run the server.

server/AdvancedChatServer.php

This file gets the sent message from server and inserts it into database. It also sends the messages in the database to the users when asked. In fact, this is the server who does everything for its clients.

You can get this file from here.

server/run-server.php

To add our “Advanced Chat” service and start the server, we must create another file :

<?php
require_once __DIR__ . "/config.php";
require_once __DIR__ . "/vendor/autoload.php";

$ip = "127.0.0.1";
$port = "8000";
  
$DS = new Fr\DiffSocket(array(
  "host" => $ip,
  "port" => $port
));
$server->run();

If you’re going to change the $ip and $port variables, you should also change the WebSocket URL in the “chat.js” file.

When you need to start the server, just run the “run-server.php” file :

php run-server.php

When new users are connected, a message will be shown in the shell that is something like this :

New connection! (29)

Each users connected (clients) will have a unique ID.

Open the website we set up, enter your name and voila !

There you go ! You just set up your own advanced chat system.