Add WebSockets to Laravel in 10 mins
This tutorial will provide a brief guide on how to incorporate WebSockets into your Laravel application. If this concept is unfamiliar to you, it is simply a protocol to send messages from server to client.
In reality, it is a full-duplex (so client to server and server to client), but we will use it only from server to client.
We do not want to use an existing provider such as Pusher; instead, we want to have everything on our own server.
A very short introduction to WebSockets
The server opens a port (e.g. 6001) for exchanging messages with connected clients. Upon connecting to the opened port, clients are able to listen to messages. Moreover, the server is able to send messages to selected clients separately or broadcast them to all clients.
Why WebSockets
Imagine you have an application with a database containing a few users. If a logged user attempts to download a CSV containing all the records, they will only have to wait a few seconds. However, if the database contains thousands or millions of records, the user must wait an extended period of time before the CSV is downloaded. Additionally, since the app utilizes an AJAX request, the user cannot perform any other action since the browser is awaiting the server's response. This is just one example of why data needs to be sent from the server to the client without an explicit request from the client (such as a live chat).
Step 1 — Project setup
I will assume you already have a Laravel application.
Let’s start by adding the laravel-websockets package to our application. This package will give us the possibility to start a WebSockets connection easily on our server (or local machine).
composer require beyondcode/laravel-websockets
We need also to publish some files (i.e. migrations, config) and run the migrations.
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
php artisan migrate
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="config"
Step 2 — Create the event
We can now create an event called SendMessageToClientEvent that will send the message to the client. Clearly, you can name the event as you want.
php artisan make:event SendMessageToClientEvent
You should see the event inside app/Events. We have to implement the interface Illuminate\Contracts\Broadcasting\ShouldBroadcast, because we need to use the method broadcastOn to specify in which channel we want to send the message. We haven’t talked about it previously, but you can specify a channel (that could be private or public) so clients will not listen to every message, but only ones which they are interested in.
You should declare here the public properties of data you want to pass. For example, I will add the property message. You can add as many as you want.
Finally, we have to give a name to the broadcasted event, which can differ from the file name. It is not mandatory, but I suggest it in order to have a more readable code.
So, this is the full SendMessageToClientEvent class.
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class SendMessageToClientEvent implements ShouldBroadcast {
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;
public string $message;
public function __construct() {
$this->message = 'Hello friend';
}
public function broadcastAs() {
return 'SendMessageToClientEvent';
}
public function broadcastOn() { // use PrivateChannel to create channels only for auth users
return new Channel('channel-name'); // enter channel name
}
}
✅ We created the event that will be dispatched to the client.
Step 3 — Front end setup
We will use Laravel Echo, a package integrated with Laravel to listen to events.
For the client side, we need to install the following dependencies:
npm install --save-dev laravel-echo pusher-js
Note: we are not using Pusher, but the package laravel-websockets has Pusher API replacement, so we will configure our frontend like it is a Pusher configuration.
Let’s add this into bootstrap.js (inside resources/js)
import Echo from "laravel-echo"
import Pusher from "pusher-js"
window.Pusher = Pusher;
window.Echo = new Echo({
broadcaster: 'pusher',
key: 'your-pusher-key',
wsHost: window.location.hostname,
wsPort: import.meta.env.VITE_PUSHER_PORT,
forceTLS: false,
disableStats: true,
cluster:import.meta.env.VITE_PUSHER_APP_CLUSTER,
});
Now, we added WebSockets support to our client, but as you can see, we are using two env variables.
In fact, we have to update our .env related to Pusher. You should find it in your environment file to match the following configuration
PUSHER_APP_ID=123
PUSHER_APP_KEY="your-pusher-key"
PUSHER_APP_SECRET=123
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1
✅ The front end is configured. Now we can start the WebSockets server and focus on the application logic!
Step 4 — Start the WebSockets server
You need only to run the following command:
php artisan websockets:serve
✅ The WebSockets server is running. The selected port (e.g. 6001) is opened.
Step 5— Make client able to listen to events
Now we have done the basic configuration. We want to see our result in the front end.
So, we can say to our blade files (for example in your welcome.blade.php) that the client should listen from the WebSocket. For this reason, you can add the following script:
<script type="module">
// the dot before the event name is not an error!
Echo.channel('channel-name').listen('.SendMessageToClientEvent',(e) => {
alert(e.message)
})
</script>
Now, every time a SendMessageToClientEvent will be dispatched from the public channel channel-name, the client will display an alert containing the message.
✅ Front end is listening for events
Step 6 — Dispatch an event to check everything is working
The last step. To dispatch the event, you can call everywhere you want the static method dispatch. For example, you can use it in your routes by typing this:
Route::get('/try-websocket', function() {
\App\Events\SendMessageToClientEvent::dispatch();
return response('try-websocket');
});
✅ Congratulations!
You configured WebSockets in your Laravel application and you sent your first message from server to client.
To deep dive into this concept, I suggest reading this RFC.
If you liked this article, feel free to share it on social media ;)