If you want to take your application’s user experience to another level and create a real-time application, you should consider using WebSockets.
There are a lot of articles on what WebSockets are, so I’ll keep this part brief. WebSockets allow bi-directional communication between a client and a server. It means that either the client can ask for data or – what’s more important – the server can send data even if the client didn’t ask for it, so data can be sent right after a change in a system and immediately presented to a user. It all takes place on a previously set channel (you can have more than one channel in your app).
What are real-life examples of using WebSockets? The first ones that should come to your mind after reading the description above are chat and notifications. Without WebSockets your clients would have to ask periodically and often “Hi server, do I have any new messages?”. If the chat is not overly active, most of the time you would get a response “No” – it’s a bit of a waste of resources, don’t you think? But, if you have WebSockets on your side, the client doesn’t have to ask about new messages every second. When the server finds out new messages arrived it will go to the client and say “Hi, man. You have new messages. You should check them out”.
Are there any other use cases? Of course there are. When more than one person works with the same resource at the same time, a server can inform a client that a resource has changed. Then your app can perform some action – update content, inform a user that something has changed and it should be checked or even block access to the resource.
When a server starts a conversation – which means broadcasts data without client’s request – you should consider it as a regular application event. In this event payload send as little data in WebSocket payload as is needed for the client to fetch it from the server – for instance send just a reference to the changed resource and let the client decide if it wants to update the user’s view. Before the event reaches the client another one changing the same resource could have occurred, therefore if you would send whole resource in payload it could be outdated at the time when client received it.
WebSockets are pretty easy to implement, both on the client- and the server-side. It’s easier to start a WebSockets server on Node.js than on PHP due to how these servers work. PHP applications have a lifetime of a request – it means that they are created when the server receives the request and after sending a response they are terminated. Node has a different lifecycle – this is the same instance for every request and is not terminated after a request is handled.
It’s harder but it’s not impossible. I personally haven’t created a WebSockets server in PHP but I’m aware that there are packages for this, i.e Ratchet or Swoole. What I’ve been using is laravel-echo-server. This package is a Node.js server which shares a database with your application and, once an event appears in the database, echo-server fetches it and sends it to the client. It has one downside though – it only allows you to push data from a server to a client. Laravel-echo-server can’t handle client’s requests over WS.
It’s pretty easy to configure and add to your project. This article describes the configuration well.
You can use multiple drivers for your broadcasting. If you want to use laravel-echo-server you should set the environmental variable to Redis or another DB driver shared with the echo server. If you don’t feel like setting up node in your environment you can use pusher.com as a driver. It requires almost nothing to configure it but has some downsides. It has a limit on payload – 10kB and it is free only to some extent, but for a start and exploration of WebSockets that may be the best choice.
To enable an event to be broadcasted you should implement the ShouldBroadcast interface in the event’s class. If everything is configured well that’s all you need to do. Laravel documentation says that you can change the broadcast name of the event. That’s only partially true. The result of this method will be sent over WebSockets, but not as broadcasted event name but rather in response payload. By default, all events are sent as \Illuminate\Notifications\Events\BroadcastNotificationCreated. I’ve created an issue once but unfortunately – despite the favorable comments of others – the pull request has been closed by Taylor.
As I mentioned at the beginning of the post, you can have more than one WebSocket channel in your application. With this approach users can join only these channels that are interesting to them and ignore events on other ones. Also, you can add authorization to channels, so that the unprivileged users won’t get into them.
If an application performs some processing on a queue the user can get notified about new data over WebSockets. The order of responses to the application events may be affected. You can deal with that in multiple ways. One way is to send as little data in WebSocket payload as is needed for the client to fetch it from the server – so send just a reference to the changed resource and let the client decide if it wants to update the user’s view. Another thing that the client can do is mark requests that were sent and for example only react to the latest one. This kind of marking can be sent in the request header and then returned in the WS response payload.
A quick sum up. WebSockets are bidirectional communication channels which allow us to create real-time applications. Their big advantage is that a server can initialize data exchange. The server should inform a client about changes in the system with the help of events – information sent in an event should only contain the required minimum to recognize what has changed. A WebSockets connection can be set up in many ways. You could use one of the existing technologies that I’ve mentioned in this post, such as Ratchet or laravel echo server or implement your own solution.