Build a Chat Messaging Platform in PHP

5 min read
Onwuka G.
Onwuka G.
Published February 26, 2020 Updated October 5, 2020

Building a fully functional and scalable chat platform is time-consuming. Luckily, Stream can help you build one in minutes!

In this tutorial, we are going to use the Stream API to build a chat messaging platform in PHP.

Prerequisites

To follow along with this tutorial, you need to have a basic understanding
of PHP and JavaScript.

You'll also want to make sure you have PHP and Composer installed on your system.

To check if you already have PHP installed on your system, run this command in your terminal:

$ php -v

If PHP is installed on your system, the version installed will be returned; otherwise, you will see “command not found: php”.

To check if you have Composer installed, run:

$ composer -v

Once you've confirmed you have the necessary languages/packages installed, let’s dive in!

Creating a Stream Account

To be able to use the Stream API, you'll need to create an account. Visit the Stream Chat website and then click on the "SIGNUP" button.

On the popup page that appears, fill in your desired username and password, along with your email address, and then click on the "CREATE FREE ACCOUNT" button:

Create Account

After creating your account, you will be taken to your Dashboard, where you'll find your APP ID, API KEY, and SECRET keys, which we’ll use to authenticate the SDK. Take note of these keys, as we will be using them in a bit:

Chat Welcome

Creating the Project

Now that we've gathered all of our "tools", create a folder named stream-chat-php in the directory where you store your code; this will be the home for all of our project files. Inside of your new stream-chat-php directory, create the following files:

  1. custom.js - this will contain our JavaScript code
  2. page.php - this will contain our chat interface
  3. server.php - this will contain our chat server logic
  4. style.css - this will contain our chat styling

Generating Tokens

We’ll be using the PHP SDK on the server and the JavaScript SDK on the client end to get realtime updates of what is happening on the chat, which includes realtime messages. To use the JavaScript SDK, we need to get a valid token, which we can generate from our PHP server.

To start, open your terminal and cd into your project root directory (stream-chat-php), then install the PHP SDK using composer:

$ composer require get-stream/stream-chat

On the prompt that appears - No composer.json in current directory, do you want to use the one at …? [Y,n]?, input n and press Enter.

Now that we have the SDK installed, we can add the following to the server.php file:

<?php

require_once(__DIR__ . "/vendor/autoload.php");

$STREAM_API_KEY = "<STREAM_APP_KEY>";
$STREAM_API_SECRET = "<STREAM_API_SECRET>";

// Initialize the SDK
$client = new \GetStream\StreamChat\Client(
   $STREAM_API_KEY,
   $STREAM_API_SECRET
);

if (isset($_REQUEST["create-token"])) {
  die(json_encode([
     "status" => "success",
     "token"  => $client->createToken($_REQUEST["create-token"])
  ]));
}

Make sure to update the <STREAM_API_KEY> and <STREAM_API_SECRET> placeholders with your correct API KEY and SECRET respectively (which we grabbed from our Stream Dashboard).

In the above code, after initializing the PHP SDK, with the if (isset($_REQUEST["create-token"])) { block, we check the request for a user's create-token variable, so we can create a token with it by calling the $client->createToken(… function.

Now that we've initiated the code for our server, we can start up the server by running:

$ php -S localhost:6060

Creating the Chat Interface

Add the below code to the page.php file to create your chat interface:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link rel="stylesheet" href="./style.css" />
    <title>Vanilla PHP and JavaScript Stream Group Chat</title>
  </head>
  <body>
    <div class="main-container">
      <div class="login" id="login-block">
        <input
          type="text"
          id="user-login-input"
          placeholder="Enter your username (should be unique)"

You may have noticed that we include a few script tags at the end of this code:

  1. The JavaScript Stream SDK allows us to use Stream in our app
  2. Axios enables us to make http requests
  3. The script tag for our custom JavaScript code will be how we connect in the magic we'll create below

Making Our App Beautiful

Building your own app? Get early access to our Livestream or Video Calling API and launch in days!

You are welcome to add your own flair to your app, but you can get started by adding the following to the style.css file:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body,
html {
  max-width: 100vw;
  max-height: 100vh;
  overflow: hidden;
  background-color: #f5f5f5;
}
.main-container {
  display: grid;
}

If you visit the project now, you will notice the page is blank: localhost:6060/page.php; we’ll be fixing this in the next step.

Initializing the JavaScript SDK

Let's get started with the client side of our app by initializing the Javascript SDK! Add the below code to your custom.js file (which, you'll remember, we referenced in the final script tag on our page.php file):

let client, channel, username;

async function generateToken(username) {
  const { token } = (
    await axios.get(`/server.php?create-token=${username}`)
  ).data;
  return token;
}

// Initialize the JavaScript chat SDK
client = new StreamChat('<STREAM_APP_KEY>');

Note: Make sure to change the <STREAM_APP_KEY> placeholder with your correct key.

Then, add the below function to the custom.js file, so that we can initialize the chat when the page is ready:

async function initializeClient(username) {
  const token = await generateToken(username);

  // Set the current logged user
  client.setUser(
    {
      id: username,
      name: 'Jon Snow', // Update this name dynamically
      image: 'https://bit.ly/2u9Vc0r'
    },
    token
  ); // token generated from our PHP server

  // create or initialize the channel
  channel = client.channel('messaging', 'general-channel1', {

Getting a User's ID

Each user needs to have a unique id that we can use to identify them. Add the below code to the custom.js file:

function checkAuthState() {
  if (!user.value) {
    document.getElementById('login-block').style.display = 'grid';
    document.getElementsByClassName('message-container')[0].style.display =
      'none';
  } else {
    document.getElementsByClassName('message-container')[0].style.display =
      'grid';
    document.getElementById('login-block').style.display = 'none';
    username = user.value;

    initializeClient(username);
  }
}

The above allows us to display the chat page and initalize the JavaScript SDK when an valid user enters their username and password. To trigger this, we'll need to listen for when the user hits Enter; add the code below to the custom.js file:

const user = document.getElementById('user-login-input');
user.addEventListener('keyup', function(event) {
  if (event.key === 'Enter') {
    checkAuthState();
  }
});

checkAuthState();

Appending New Messages

In order to add each new message that comes in to the chat, add the below function to the custom.js file:

// [...]
function appendMessage(message) {
  const messageContainer = document.getElementById('messages');

  // Create and append the message div
  const messageDiv = document.createElement('div');
  messageDiv.className = `message ${
    message.user.id === username ? 'message-right' : 'message-left'
  }`;

  // Create the username div
  const usernameDiv = document.createElement('div');
  usernameDiv.className = 'message-username';
  usernameDiv.textContent = `${message.user.id}:`;
  // Append the username div to the MessageDiv

This function will take in the message payload (that contains the user's username and message), create a new Node element that holds the username and message, and then attach the message to the page using the message's id.

In the UI, that will look something like this:

Message Div

Juggling New and Old Messages

Let's start by listening for new messages coming to the channel! Add the below code to the initializeClient(username) function at the top of custom.js:

async function initializeClient() {
  // [...]
  channel.on('message.new', event => {
    appendMessage(event.message);
  });
}

Now, what about old messages on the channel already? We need to render those as well... To accomplish this, add the following to the initializeClient() function:

async function initializeClient() {
  // [...]
  channel.state.messages.forEach(message => {
    appendMessage(message);
  });
}

Sending Messages

So far, we can see previous messages and new messages added to the channel. Next, we will add functionality to allow users to send a new message to the channel.

Add the below function to the custom.js file:

async function sendMessage(message) {
  return await channel.sendMessage({
    text: message
  });
}

Next, listen for the message-input and for when the user hits Enter, so we can send the message to the channel:

const inputElement = document.getElementById('message-input');
inputElement.addEventListener('keyup', function(event) {
  if (event.key === 'Enter') {
    sendMessage(inputElement.value);
    inputElement.value = '';
  }
});

Testing It Out

To test out the chat:

  1. Open the application in two different tabs or browsers.
  2. Type in a username and hit Enter, in each.
  3. Exchange messages!
Demo

Conclusion

We have covered the basics of getting started with Stream Chat using the PHP SDK to power your chat. There are lots of amazing chat features that you can add to your chat, like the "is typing" indicator, online presence, and much more!

Please reach out and share your incredible creations with us; until then, happy coding!

decorative lines
Integrating Video With Your App?
We've built an audio and video solution just for you. Launch in days with our new APIs & SDKs!
Check out the BETA!