Here we load the namespaces for the Ratchet libraries and our own Chat class that will handle the chat messages. Composer creates an autoloader for us that we can use to load the class names, so we require that. Then we create a web socket server, give it our Chat handler class, and tell it to listen on port 8080. Ratchet provides several components that you can choose from. Here we’re using the WsServer (WebSocket server) component.

Note that our Chat class implements the “MessageComponentInterface” provided by the Ratchet WsServer component. That interface exposes 4 events that our server can listen for, so we register a callback function for each one. See the WsServer documentation for more details.

When we start up our socket server a new instance of our Chat class is created. The constructor simply creates an object to store client connections in.

The onOpen event fires when a new client connects to the socket server. This function stores the new connection and sends the client a welcome message. We’re also printing out the connection ID to the shell where the server is running.

The onClose event fires when a client connection is closed (user closes the browser window). We remove that client from our storage and print out another message to the server shell.

The onError event fires when we encounter a connection error. We print out the error message to the terminal and close the connection.

The onMessage event is where the magic happens. This event fires when the socket server receives a message from one of the connected clients. We loop through all the connected clients and send that message out to each one. This keeps the clients in sync, so that when one user posts a message it gets broadcast out to all the other connected clients.

This is pretty straight forward. We have an unordered list that will get populated with the chat messages, and a form for posting new messages.

In the header we’re loading two scripts. This example uses jQuery, so you need that. I’ve loaded it using Bower, but you can link to it however you want. The other script (app.js) is our client-side application code that we’ll get to next.

public/app.js

// initialize messages arrayvarmessages=[];// connect to the socket servervarconn=newWebSocket('ws://localhost:8080');conn.onopen=function(e){console.log('Connected to server:',conn);}conn.onerror=function(e){console.log('Error: Could not connect to server.');}conn.onclose=function(e){console.log('Connection closed');}// handle new message received from the socket serverconn.onmessage=function(e){// message is data property of event objectvarmessage=JSON.parse(e.data);console.log('message',message);// add to message listvarli='<li>'+message.text+'</li>';$('.message-list').append(li);}// attach onSubmit handler to the form$(function(){$('.message-form').on('submit',function(e){// prevent form submission which causes page reloade.preventDefault();// get the inputvarinput=$(this).find('input');// get message text from the inputvarmessage={type:'message',text:input.val()};// clear the inputinput.val('');// send message to serverconn.send(JSON.stringify(message));});});

This code runs in the client browser and allows it to connect to the socket server and send and receive messages. The W3C WebSocket API exposes the same 4 events that we saw in our server code, and we define a callback function to handle each one. Note that these event names are all lower-case though.

The onopen event fires when our client connects to the socket server. We log a message to the browser’s console.

The onerror event fires when we have a connection error.

The onclose event fires when our client closes its connection to the socket server.

The onmessage event fires when the client receives a message from the socket server. Each of these callbacks receives an event object as an argument (I assigned to the variable “e”). The actual payload of the message is contained in the event object’s “data” property. Here we grab the message, log it to the console, and then append it to the unordered list using jQuery.

The last piece of code uses jQuery to add an event handler to the message form. When we submit that form, we want the client to send the message we typed to the socket server. Here we grab the value of the text input, create a message object, clear the input, and then send the message to the server. This action will fire an “onMessage” event on the server, which will respond by sending that message out to all the connected clients as we saw in the server code earlier.

Running the app

To run the app you’ll need to install the PHP libraries on your server. Composer will handle that for you. Open a shell terminal on your server, navigate to the project directory and type:

composer install

If you’re using the Bower file for the client libraries, type:

bower install

Then start up the web socket server we created which will listen for message events:

php bin/server.php

That will run the socket server code which will start listening for connections and events on port 8080. Then open up two browser windows and point them to wherever you’re hosting the project and start chatting!