Starting from this article, I want to review some interesting cases that I encounter during my work when creating web applications.

Today I want to talk about how to configure Laravel Websockets to receive notifications in NuxtJs.

To get started, we need to understand when to use WebSockets. Usually they are used when developer want to get some information by API, without the need to refresh the page or regularly ping using JavaScript. Perhaps the most common use cases for WebSockets are to receive new messages in open chats and to receive notifications.

Laravel Websockets have three types of channels: public – which anyone can subscribe to, private – channels requiring user authorization, which check whether they have the right to listen to this channel and presence – channels that do not send messages, but only notify if the user listening this channel. In this article, I will describe an example of subscribing from NuxtJs to a private Laravel channel.

Requirements

  • Laravel framework (version 6.11)
  • Nuxt.js (version 2.11)
  • Redis server

Configuring Laravel API as a backend for WebSockets

First of all, we need Redis to broadcast events to channels. In this article, we will assume that it is already installed on your server, since its installation is a separate big topic, and we will not consider it within this post. Now we will install the Predis package that Laravel needs to work with the Redis repository.

In the .env file, add or update the following data:

BROADCAST_DRIVER=redis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

In the config/app.php file, enable the BroadcastServiceProvider in the providers array, just uncomment it:

App\Providers\BroadcastServiceProvider::class,

Now in \app\Providers\BroadcastServiceProvider.php at the beginning of the boot method add the line:

Broadcast::routes(['middleware' => ['auth:api']]);

It is needed in order to add middleware to check user authentication by API.

Now in \routes\channels.php create a new channel:

Broadcast::channel('user_notifications.{user_id}', function($user, $user_id) {
    return (int) $user->id === (int) $user_id;
});

It also checks that the id of the authorized user matches the id of the channel to which he subscribes (so that the user does not subscribe to the channels of other users).

Now we need to create an event, for this we enter the command:

php artisan make:event NotificationEvent

After that, you will see the file \app\Events\NotificationEvent.php , which can be fill as follows:

<?php

namespace App\Events;

use App\Models\User;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class NotificationEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $notifications;

    /**
     * NotificationEvent constructor.
     * @param User $user
     */
    public function __construct($user)
    {
        $this->notifications = [
            'user_id' => $user->id,
            'notifications' => $user->notifications,
        ];
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new PrivateChannel('user_notifications.' . $this->notifications['user_id'] );
    }
}

Here in __construct we pass the user model and assign an array containing the user id and its notifications (which are set in the model) to the class variable $notifications. And in the broadcastOn method, we return the PrivateChannel with the name of the channel passed as an argument.

Now in the place where you will need to send notifications to the user with id 1 (for example, in the controller) you will need to call the event method as follows.

$user = User::where('id', 1)->first();
event(new \App\Events\NotificationEvent($user));

Configuring NuxtJs as a frontend

To start configuring Websockets in NuxtJs we have to install the socket.io client and the laravel-echo package:

npm install --save laravel-echo
npm install --save socket.io-client

Now in nuxt.config.js file add the following:

buildModules: [
  '@nuxtjs/laravel-echo',
],
echo: {
    broadcaster: 'socket.io',
    host: 'http://localhost:6001',
    plugins: [ '~/plugins/echo.js' ],
},

In host, instead of localhost, specify the location where your Laravel API is located, and leave port 6001 unchanged.

Next in Nuxt, create the file \plugins\echo.js

export default function ({ $echo }) {
    // Echo is available here
}

Then on any page, for example, inside mounted method, you can subscribe to private channels:

mounted() {
        let authData = {
            headers: {
                Authorization: 'Bearer ' + this.$store.getters['authUser/User'].api_token,
                Accept: 'application/json',
            },
        };
        this.$echo.connector.options.auth = authData;
        this.$echo.options.auth = authData;
        this.$echo.private('user_notifications.' + this.$store.getters['authUser/User'].id)
            .listen('NotificationEvent', (e) => {
                console.log(e.notifications); 
            });
},

In the code above, we take the api token from the store, which we will authorize in Laravel. And then we subscribe to the private channel, transferring the user id and indicate the previously created NotificationEvent.

Websockets configuration is almost complete, all that remains is to install Laravel Echo Server.

Install and configure Laravel Echo Server. Autorun server

Go to the folder with Laravel and run the command:

npm install -g laravel-echo-server

Now initialize the Laravel Echo Server.

laravel-echo-server init

When you run this command, you will be asked several questions necessary to configure the server.

Initialize Laravel Echo Server

When answering, do not forget to specify your host, you can leave everything else by default (just do not forget to turn off development mode when you upload it to production).

After that, the laravel-echo-server.json file will appear in the application folder, where you can change all the settings if necessary.

Now all that remains for you is to launch Laravel Echo Server with the command:

laravel-echo-server start

If you did everything correctly, then you will see the following message.

Laravel Websockets can work (Laravel Echo Server started successfully)

Congratulations, your WebSocket notifications should work now.

However, in order not to keep our last command constantly running to the command line, it is best to run it in the background mode. This can be done using the daemon process manager PM2. Let’s install it:

npm install -g pm2

Now let’s tell the manager to start when system startup and add our script to it.

pm2 startup
pm2 start laravel-echo-server.js

Done! If you did everything correctly, then you will successfully start receiving notifications using Laravel Websockets in NuxtJs application.

Share post
Twitter Facebook