Real time PHP website with web sockets (Ratchet), we’ll be taking a look at Ratchet, a PHP library for working with WebSockets. Let’s start by defining what WebSockets are
WebSockets is an advanced technology that makes it possible to open an interactive communication session between the user’s browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.
First, let’s install Ratchet using Composer:
composer require cboden/ratchet
Now we’re ready to build the app. Create a Chat.php
file under the class/ChatApp
directory. This would be a class under the ChatApp
namespace, and it would use use Ratchet’s MessageComponentInterface
and ConnectionInterface
. The MessageComponentInterface
is used as the basic building block for Ratchet applications, while the ConnectionInterface
represents the connection to the application.
<?php
namespace ChatApp;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
Have the class implement the MessageComponentInterface
. This contains the blueprint for the methods that we need to implement such as onOpen
, onClose
and onMessage
.
class Chat implements MessageComponentInterface {
}
Inside the class, we declare a variable called $clients
. This is where we will store a list of currently connected clients in our chat app later on. From the constructor, you will see that we’re using SplObjectStorage
. This provides a way for us to store objects. In this case, the object that we need to store is the connection object for each client.
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
}
Next, we implement the onOpen
method. This method is called every time a new connection is opened in the browser. What this does is store the new connection object using the attach
method. We also output that someone has connected as a means of testing if the onOpen
method is working correctly.
public function onOpen(ConnectionInterface $conn) {
//store the new connection
$this->clients->attach($conn);
echo "someone connected\n";
}
Next is the onMessage
method. This method is called every time a message is sent by a specific client in the browser. The connection object of the client who sent the message, as well as the actual message, are passed along as an argument every time this method is called. All we do is loop through all the currently connected clients and send the message to them. In the code below, we’re checking if the client in the current iteration of the loop is the one who sent the message. We don’t want to send the same message to the person who sent it.
public function onMessage(ConnectionInterface $from, $msg) {
//send the message to all the other clients except the one who sent.
foreach ($this->clients as $client) {
if ($from !== $client) {
$client->send($msg);
}
}
}
Next is the onClose
method. As the name suggests, this method is called every time a client closes the WebSocket connection from the browser. This method is triggered when a user refreshes the browser tab or closes it entirely. All we have to do is call the detach
method on the list of clients and pass in the connection as an argument. This deletes that specific connection.
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
echo "someone has disconnected";
}
Lastly, we have the onError
method which is fired every time there’s a connection error. When this happens, we output the error that occurred and then call the close
method in the connection to close it.
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$conn->close();
}
Now we’re ready to create the entry file which will utilize the file we’ve just created. We will be running it from the command line. Call it cmd.php
, save it in the root of your working directory, then add the following code.
<?php
require 'vendor/autoload.php';
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use ChatApp\Chat;
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
$server->run();
What this file does is create a new WebSocket server that runs on port 8080. We will connect to this server later on from the client side.
Before we move on, let’s break down the file. First we include the autoload file so that we can use the different Ratchet components from our file.
require 'vendor/autoload.php';
Next, we specify which specific components of Ratchet we need. For this chat application we would need the IoServer
, HttpServer
and the WsServer
.
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
Here’s a brief description of each of the components:
IoServer
allows us to receive, read and write, and close connections, as well as handle errors that we might get. This provides basic server functionality as well, so we can use it to create a new server instance.HttpServer
allows us to parse incoming HTTP requests. This component is used every time a user connects to the server or a user sends a message.WsServer
is the WebSocket server. This allows us to talk to browsers which implement the WebSocket API. Most modern browsers already implement WebSockets so there won’t be a problem if you’re not planning to support old browsers. If you do, then you can take a look at adding a Flash Policy to your application.Going back to the cmd.php
file, we also use the Chat
class that we created earlier.
use ChatApp\Chat;
Once that’s done, we can create the WebSockets server. For that, we would need to call the factory
method on the IoServer
component and then pass in a new instance of the HttpServer
. This new HttpServer
instance then accepts a new WsServer
instance. Finally, we pass in a new instance of the Chat
class to the WsServer
. You can see which specific server component wraps what in the documentation.
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
We run the server by calling the run
method.
$server->run();
At this point you can start running the server from the terminal:
php cmd.php
wordpress theme by initheme.com