Web sockets made easy with Laravel and Ratchet
In this article we’ll learn how create a simple websocket server in Laravel using Ratchet php library but, before we start make sure that the server you’re going to develop on supports the websocket protocol ws and for the secure connection wss protocol should be also available, how to configure server to support ws and wss protocols will be covered in another article soon.
First we need to include Ratchet into our Laravel project using composer by running the following command on your server at the project’s root directory
composer require cboden/ratchet
And after it gets installed we can go on with creating websocket server script, which will be running in background waiting for and managing connections.
Setting up Websocket server
The websocket server is a background job that is kept running for managing connections between connecting peers, in Laravel we’re going to create that server in an artisan command, in case if you don’t know what an artisan command is, shortly it’s a script that can be run from terminal with the name you choose for it. Let’s create our server initialization console command, on terminal at your project’s root enter the following:
php artisan make:console WebSocketServer --command=websocket:init
Once you run the command above you’ll find a new php class created for you in “/app/Console/Commands/WebSocketServer.php”, on Laravel 5.2 and above you’ll need to write the following code snippet in the “handle” method of that class, in older Laravel versions the same code should be written in the “fire” method of the class.
So after editing the class it should look something like this
The code above is run when you enter the command “php artisan websocket:init” in terminal, please note if you run it right now it won’t work because, we haven’t created the “WebSocketController” class yet, the purpose of the code above is to start a server handling incoming connections and sending messages between the connecting peers using your application, the management itself happens in the “WebSocketController” that we’re going to create next.
But before going to the next point let’s have a quick look at the command we’ve just created, when this command is called the “handle” method will be called running whatever it includes, the “$server” variable we’ve defined is an instance of “IoServer” class which handles input and ouput of the peers connected to the socket, it wraps an instance of “HttpServer” which receives connection requests from peers and responds to them, finally the latter wraps the “WsServer” which is the websocket server manages the websocket connection parameters between peers such as the protocol version, now we need to provide our own way of handling those connections between our users and that is achieved by providing an instance of our “WebSocketController” that we’ll develop in the next section of this article.
Developing the Websocket controller
Here we’ll develop the class that will do the work for the connected parties, it is a standard Laravel controller so that we can use any of the installed packages and services to be provided to the connected peers, in the directory “/app/Http/Controllers” create the file “WebSocketController.php” and copy the following code in it.
That’s it the server script is ready to be run and receive connections, but let’s review that controller code, mainly the controller implements the Ratchet interfaces that is used on four states that a connected peer gets through and, it includes a variable that has the connected peers saved. the four states that any of the connecting peers go through that are expressed by the callback methods defined in the controller class above.
“onOpen” is the first function called whenever a new client connects to the websocket server, what it does that it saves the connected peer ID that is automatically generated by Ratchet in the “resourceId” property of the connection object, while saving the new connection data a room will be kept for a custom ID that we’ll set for the user afterwards.
“onMessage” is the function that is called when a client sends a new message to the websocket, this function is the hub that connects the peers i.e. the clients with one another, it takes the message sent by a peer and we decide how to handle that message, we can send it to all other clients or to specific client depending on the message format we decide on the client side. For example this function in the code above, checks for custom user ID of the sending peer if it is not there then that message is an initialization message to save the custom ID to that connection, otherwise it is a normal message that shoould to be sent to the specified peer as defined in the message. Of course we can handle that message differently, it’s up to you what you should do to that message.
“onError” is the function that is invoked when a client has an error related to its connection with the websocket.
“onClose” is the function that is invoked when a client becomes disconnected with the server as you can see from the code above, all online clients are notified of that disconnected peer.
Running the Websocket server
Now to the final step on the server side to start running our websocket server, we have to tell Laravel about the command we have created so when we go to the terminal and write “php artisan websocket:init” the command runs and doesn’t give us an error telling us the command you’re trying to run is not recognized so, let’s tell Laravel about our server command in “app/Console/Kernel.php” class, you’ll just need to add the next line to the “$commands” array.
Now let’s run the server but, please note that when the command runs it will take control of the terminal and you won’t be able to write, and if you close it the websocket server will shut down so let’s run it in a way that it will never exit even if we close the terminal. On terminal at the root directory of your project, write the command as following.
nohup php artisan websocket:init > websocket.log &
That’s it, if everything went right, you’ll find the file “websocket.log” empty, and your server is ready to receive websocket connections on “localhost:8090” or if you’re running on an online domain you should receive connections on “your-domain:8090”, the port is 8090 because it is set in the websocket command class in the first step above. How to set custom URL to receive the websocket connections on will be covered in another article later on, along with the client side code used to connect to the websocket server, to complete the real time application.
Thanks for taking the time to read this explanation of running a websocket server with Laravel and Ratchet.