Leveraging Laravel WebSockets : A Practical Guide
Tags: laravel, php, tutorial, websockets
Published: 2023-06-15 09:38:53

In this tutorial, we will explore the concept of WebSocket API or WebSockets and its significance in real-time applications. Unlike traditional HTTP requests, WebSocket provides a two-way communication channel between the server and the client.

When using Ajax (Axios, Fetch), we can send and receive data from the server without reloading the page. However, this approach relies on one-way communication, where the server cannot send data to the client without a prior request. This limitation becomes evident in scenarios like an Ajax chat application, where we constantly need to send requests to check for new messages.

To overcome this challenge, WebSockets come into play by establishing a persistent, interactive connection session between the server and the user's webpage. This connection allows for continuous communication, resembling a phone call between the server and the browser. Once initiated, the server can send messages or objects to the webpage at any time, without the need for repetitive polling.

By leveraging WebSockets, we can create real-time applications where the server can instantly send data to the webpage. For example, consider the Facebook notification system that informs users about post likes. When someone likes a post, the server triggers a like event and promptly sends a WebSocket message notification, such as "Someone likes your post."

Through this tutorial, we will explore how to set up a Laravel WebSockets server, enabling real-time functionality using Laravel 9. Stay tuned for a step-by-step example and practical implementation.

**Laravel WebSocket concept**
In Laravel, the concept of WebSockets revolves around creating channels and broadcasting events to provide real-time, live-updating user interfaces. Here's a breakdown of the Laravel WebSocket concept:

**1-Channel Creation**: In Laravel, you can define channels in the routes/channels.php file. These channels act as communication pathways between the server and clients.

**2-Broadcasting Events**: To send real-time updates, you can broadcast Laravel events on specific channels. When an event is triggered, the message associated with it will be sent to all clients subscribed to that particular channel.

**3-Subscribing to Channels**: Clients, typically web browsers, can subscribe to specific channels to receive messages sent by the server. This allows for real-time updates without the need for constant polling.

We can install Laravel-websockets package via composer.

```
composer require beyondcode/laravel-websockets
```

The package comes with migration to save statistical information about the running WebSockets server.

```
php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
```
And publish the WebSocket configuration file

```
composer require pusher/pusher-php-server "~3.0"
```
We need to make our BROADCAST_DRIVER to be pusher in .env file.

```
BROADCAST_DRIVER=pusher
```
To configure Pusher for Laravel WebSockets in the config/broadcasting.php file, you can modify the configuration as follows:

```
        'pusher' => [
            'driver' => 'pusher',
            'key' => env('PUSHER_APP_KEY'),
            'secret' => env('PUSHER_APP_SECRET'),
            'app_id' => env('PUSHER_APP_ID'),
            'options' => [
                'cluster' => env('PUSHER_APP_CLUSTER'),
                'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com',
                'port' => env('PUSHER_PORT', 443),
                'scheme' => env('PUSHER_SCHEME', 'https'),
                'encrypted' => true,
                'useTLS' => env('PUSHER_SCHEME', 'https') === 'https',
            ],
            'client_options' => [
                // Guzzle client options: https://docs.guzzlephp.org/en/stable/request-options.html
            ],
        ],
```
and in .ENV add pusher app key ,secret ,host , port , schema and cluster

```
PUSHER_APP_ID=local
PUSHER_APP_KEY=local
PUSHER_APP_SECRET=local
PUSHER_HOST=127.0.0.1
PUSHER_PORT=6001
PUSHER_SCHEME=http
PUSHER_APP_CLUSTER=mt1
```
now we can use WebSockets

```
php artisan websockets:serve
```
and in different terminal run laravel server and go 
http://127.0.0.1:8000/laravel-websockets
to see dashboard 

```
php artisan serve
```
**Broadcasting Laravel Event on a public channel**
To enable our server to send messages to the client in a public channel that doesn't require authentication, we'll begin by creating an event. This event will serve as a trigger for broadcasting messages.

```
php artisan make:event PublicMessageEvent
```
To broadcast our event using the ShouldBroadcast interface, we need to implement it in our event class (app\Events\PublicMessageEvent.php in your example). This interface provides the necessary methods to broadcast the event and specify the channel to broadcast on.

```
<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Http\Traits\WebSocketsTrait;


class PublicMessageEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels,WebSocketsTrait;

    /**
     * Create a new event instance.
     */
    public $data;
    public function __construct()
    {
        //
    }



    /**
     * Get the channels the event should broadcast on.
     *
     * @return array<int, \Illuminate\Broadcasting\Channel>
     */
    public function broadcastOn()
    {
        $this->data = $this->status();

        return [
            new Channel('public'),
        ];
    }
}
```
By default, the event will be stored in a queue job but if you want to broadcast immediately use ShouldBroadcastNow interface.

and in web add that route 

```
Route::get('/status', [\App\Http\Controllers\WebSocket::class, 'status']);
```
you can broadcast the event and create method in controller 

```
<?php

namespace App\Http\Controllers;

use App\Events\PublicMessageEvent;
use Illuminate\Http\Request;

class WebSocket extends Controller
{
    public function status () {
         broadcast(new PublicMessageEvent());
    }
}

```
I utilize the WebSocketsTrait to broadcast messages, eliminating the need to navigate to a specific channel.

```
<?php

namespace App\Http\Traits;

use App\Models\User;

trait WebSocketsTrait
{
    public function status()
    {

        return User::all();
    }


}

```
**Notice you don’t have to declare a public channel in routes\channels.php**

now all things look fine 

To begin, follow these steps to open the Laravel WebSockets dashboard and establish a connection:
**1-open the Laravel websockets dashboard** http://127.0.0.1:8000/laravel-websockets

**2-click connect button and make sure you use the port 6001**  
then in another browser tab go to http://127.0.0.1:8000/status
you should see all Users .
you can see channel name and the event name as well in  api-message in WebSockets dashboard.

**To listen for the event broadcasted from the Laravel backend in frontend frameworks like Vue, React, or any other framework, you can utilize Laravel Echo. Laravel Echo is a JavaScript library that simplifies the process of subscribing to channels and listening for events.**

**CONCLUSION**
In conclusion, by integrating Laravel WebSockets into your backend infrastructure, you can unlock the potential of real-time communication between the server and the client. Leveraging WebSockets allows you to establish persistent connections, enabling bidirectional data flow and facilitating the development of dynamic and interactive applications. By following the steps outlined in this tutorial, you'll have the foundation to implement Laravel WebSockets and leverage its power in your backend architecture. Happy coding!