Realtime Messaging with PushRadar, PHP, HTML & jQuery

Download code (38.7KB, .zip)
Realtime Messaging with PushRadar, PHP, HTML & jQuery

In this blog post, I will show you how to build a realtime instant messenger with PushRadar, PHP, HTML & jQuery. PushRadar is a realtime notifications API service for the web, that allows you to broadcast data from your server and receive it client-side in realtime using JavaScript. We will take advantage of PushRadar's user targeting functionality to broadcast new messages on user channels.

You can download the full source code of this solution as a zip file using the 'Download code' link at the top of this page.

Prerequisites

In order to follow along this guide or run the attached code, you will need the following:

  • PHP 5.3.3 or later (PHP 7.1 preferable for speed improvements)
  • A PushRadar account - you can sign up for free by clicking here

Live demo

If you would like to run a live demo of the finished product, download the attached code, and upload the files in the InstantMessaging folder to your server.

  • Replace your-secret-key inside messaging.php with your actual PushRadar API secret.
  • Replace your-api-key inside chat.php with your actual PushRadar API key.
  • Run the index.php file in one web browser or tab. When it opens, select "User 1".
  • Run the index.php file in a second web browser or tab. When it opens, select "User 2".
  • Send a message from one chat window, and it will instantly appear in the other.
You can obtain your PushRadar API credentials from the API page of your dashboard (dashboard.pushradar.com/api).

Getting started

First of all, let's configure a new directory for our PHP project. Go ahead and create an empty folder on your system called InstantMessaging. We are going to be using Composer to manage our project's dependencies. If you haven't used Composer before, it is a useful command-line tool that allows you to install and update packages automatically. You can download and install it from here.

Change directory to the one you just created by running the following command from your console:

cd "your/path/to/InstantMessaging"

For the realtime messaging functionality, we will need PushRadar's PHP library. To install it, run the command composer require pushradar/pushradar-php. Composer should create a composer.json file and a vendor folder, containing the latest version of PushRadar's PHP package.

Create an index.php file within the InstantMessaging folder with the following content:

  • index.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>InstantMessaging</title>
</head>
<body>
Select a user to send messages as:<br/><br/>
<div>
    <a href="./chat.php?user=1">User 1</a> |
    <a href="./chat.php?user=2">User 2</a>
</div>
</body>
</html>

The index.php file allows us to simulate being two users; when we have completed our instant messenger, we will run this file from two web browsers, selecting 'User 1' on the first and 'User 2' on the second, proceeding to send messages between them.

Coding the UI

Create a file in the InstantMessaging root directory called chat.php. This page will form the main user interface of our project. It will contain a scrolling chat window displaying the conversion between the two users, a textarea control for writing a message and a send button for sending messages. Copy and paste the following code into the file:

  • chat.php
<?php

// Make sure that a user ID has been passed in the query string
if (!isset($_REQUEST["user"]) || !in_array($_REQUEST["user"], array("1", "2")))
    header('Location: ./index.php');

// Get the user ID and the chat partner's ID
$user_id = (int)$_REQUEST["user"];
$chat_partner_id = ($user_id == 1 ? 2 : 1);

?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>InstantMessaging</title>
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
    <link rel="stylesheet" href="./styles.css">
</head>
<body class="instant-messaging">

<ul id="messages">
    <li class="no-messages">No messages...</li>
</ul>

<div id="message-input-container">
    <textarea id="message" placeholder="Type a message to user <?php echo $chat_partner_id; ?>:"></textarea>
    <div id="send-btn-container">
        <button id="btn-send">Send message</button>
    </div>
</div>

</body>
</html>

Let's go through the above code step by step. First of all, there is a check for the user query string parameter, accessed through the $_REQUEST superglobal. The user parameter contains the ID of the current user and for this example can be either '1' or '2'. Clicking one of the links on the index.php page redirects to chat.php, adding the user ID to the url automatically. The user ID is stored in a variable, as is the chat partner's ID so that we know who we are sending messages to.

Looking at the <head> section of the code, you will notice that two libraries are referenced, jquery.min.js and moment.min.js. We will be using Moment.js for datetime formatting and jQuery for updating the UI. We also link to a stylesheet which we will create next. The rest of the HTML code sets out the basic user interface, with dynamic placeholder text inside the textarea control which shows "Type a message to user 2" if we are viewing the page as user 1, and "Type a message to user 1" if we are viewing the page as user 2.

Inside the InstantMessaging base directory, create a styles.css file containing the following code:

  • styles.css
.instant-messaging #messages {
    height: 180px;
    margin-bottom: 20px;
    max-width: 535px;
    overflow-y: scroll;
}

.instant-messaging #message-input-container {
    width: 100%;
}

.instant-messaging #message {
    width: 100%;
    max-width: 570px;
    height: 100px;
}

.instant-messaging .no-messages {
    color: gray;
    list-style-type: none;
    margin-bottom: 10px;
}

.instant-messaging .message-item strong {
    margin-right: 10px;
}

.instant-messaging .message-item {
    margin-bottom: 12px;
}

.instant-messaging .message-item small {
    color: gray;
    margin-top: 5px;
    display: block;
}

Coding the backend

We will soon return to our chat.php file to add JavaScript functionality, but first we need to code up the backend of our messaging system. The backend script will receive messages, broadcasting them to the chat partner of the sender (user 2 if the sender is user 1, or user 1 if the sender is user 2). Create a new messaging.php file in the InstantMessaging directory with the following code:

  • messaging.php
<?php

use PushRadar\PushRadar;

// Auto-load project dependencies
require_once("./vendor/autoload.php");

// Set the default timezone to UTC
date_default_timezone_set("UTC");

// Get the POST content
$data = array();
$post_content = file_get_contents("php://input");
if (trim($post_content) == "") die("You should not directly access this page.");
parse_str($post_content, $data);

// Get the message, user ID and chat partner ID
$message = $data["message"];
$user_id = (int)$data["user_id"];
$chat_partner_id = ($user_id == 1 ? 2 : 1);

// Create a new PushRadar object
// TODO: Replace "your-secret-key" below with your actual PushRadar API secret. You can obtain this from https://dashboard.pushradar.com/api
$radar = new PushRadar("your-secret-key");

// Create the data array to send to the chat partner
$data = array(
    "sender" => array(
        "name" => "User " . $user_id,
        "id" => $user_id
    ),
    "content" => $message,
    "sent_at" => date("Y-m-d, H:i")
);

// Broadcast the data to the chat partner's "new message" channel
$radar->targetUser($chat_partner_id)->broadcast("user:new-message", $data);

The comments in the code above should give you a general idea about what is going on, but let's cover a few points in greater detail. For this example, we set the default timezone to UTC, but in a production system you may like to implement your own timezone handling code. The POST-ed data is read from the php://input temporary file, and parsed into a local array, identified as $data. The two data items that are sent through to this script, message and user_id, along with the chat partner's ID, are also saved into individual variables for later use.

Right at the top of the script you will see that we require_once Composer's autoloader from the vendor directory. This loads PushRadar's library automatically. After the data variables have been saved, we create a new PushRadar object.

Replace your-secret-key in the code above with your actual PushRadar API secret. You can obtain this from the API page of your dashboard (dashboard.pushradar.com/api).

Having made a new PushRadar object, we construct the data which will be sent over to the user's chat partner. The data items that we will include are the sender's details (name and id), the message content and the date and time that the message was sent (sent_at).

The final line of code in this file broadcasts the data using PushRadar. The targetUser method specifies the ID of the user to send the data to (the chat partner's ID), and the data is broadcasted on the user:new-message channel.

JavaScript functionality

All that's left to do is to add some JavaScript client-side code to receive and display new messages. Return to the chat.php file we created earlier and add the following code just before the closing </body> tag:

  • chat.php (before </body> tag)
<!-- Include the PushRadar JavaScript library -->
<script src="//www.pushradar.com/pushradar.js"></script>
<script>

    // Set the user ID in JavaScript
    var user_id = <?php echo $user_id; ?>;

    // Create a new PushRadar object, setting the current user's ID as the second parameter
    // TODO: Replace "your-api-key" below with your actual PushRadar API key. You can obtain this from https://dashboard.pushradar.com/api
    var radar = new PushRadar("your-api-key", user_id);
    radar.subscribe("user:new-message", function (message) {

        // Remove the 'no-messages' item if it is displayed
        $('.no-messages').remove();

        // Add the new message to the UI
        var messages_window = $('#messages');
        messages_window.append('<li class="message-item"><strong>' + message.sender.name + ':</strong>' +
            message.content + '<br /><small>(' + message.sent_at + ' UTC)</small></li>');

        // Scroll to the end of the messages window
        messages_window.scrollTop(messages_window[0].scrollHeight);

    });

    // Handle clicks on the send button
    $('#btn-send').click(function () {

        // Validate the message field
        var message_field = $('#message');
        var message_content = message_field.val();
        if (message_content == "") {
            alert("Please enter a message.");
            return;
        }

        // Send the message to the server using ajax
        $.post("messaging.php", {"message": message_content, "user_id": user_id});

        // Remove the 'no-messages' item if it is displayed
        $('.no-messages').remove();

        // Update the user interface
        var messages_window = $('#messages');
        messages_window.append('<li class="message-item"><strong>You:</strong>' +
            message_content + '<br /><small>(' + moment.utc().format('YYYY-MM-DD, HH:mm') + ' UTC)</small></li>');

        // Clear the message field
        message_field.val("");

        // Scroll to the end of the messages window
        messages_window.scrollTop(messages_window[0].scrollHeight);

    });

</script>
Replace your-api-key in the code above with your actual PushRadar API key. You can obtain this from the API page of your dashboard (dashboard.pushradar.com/api).

Let's take apart the code above. First off, the current user's ID is transferred into a javascript variable with a simple PHP echo statement. We then create a new PushRadar object, passing in our PushRadar API secret, and the current user's ID. Passing PushRadar a user ID allows you to take advantage of the service's user targeting functionality; you can broadcast notifications to a particular user by calling targetUser() server-side, as you have seen in messaging.php.

The line radar.subscribe(...) subscribes to the user:new-message channel, receiving new messages in realtime. The message parameter of the callback corresponds to the JSON-serialized $data array that we created in messaging.php. Notice how array items such as the sender's name can be accessed using dot notation from within the callback (message.sender.name). Our custom callback formats and displays received messages on screen.

jQuery is used to handle click events on the send message button. Within the event handler, we perform basic validation on the textarea field and if a message has been input, it is sent to our backend script via Ajax. Additionally, the sent message is added below the current items in the conversation window.

The finished product

Congratulations for making it to the end! You should now have everything you need to run the finished product. Upload the files in the InstantMessaging folder to your server, and then follow the instructions below.

  • Run the index.php file in one web browser or tab. When it opens, select "User 1".
  • Run the index.php file in a second web browser or tab. When it opens, select "User 2".
  • Send a message from one chat window, and it will instantly appear in the other.
You can download the full source code of this solution as a zip file using the 'Download code' link at the top of this page.