close

Somewhere, in a parallel universe,
the-other-you just clicked on
"Subscribe To Our Monthly Newsletter"

The-other-you seems eager to stay updated with the technological changes.

Please enter your name. Please enter your name.
Please enter your email. Please enter your email.

A 5-Step Approach To Integrate Real-Time Broadcasting In Laravel

Post by|Laravel12 October,2020
165 View

When you think of real-time applications in Laravel, pairing the Redis broadcaster with a Socket.IO server is a good start. There are a plethora of Laravel development companies that may differ from our 5-step approach, but these five steps made our Laravel web development project a cake-walk.

Here are five simple steps you need to follow to implement to integrate broadcasting:

  1. Configure Redis
  2. Create Event And Fire Event
  3. Install Required Packages
  4. Configure Socket.IO
  5. Setup Websocket And Consume Data

Step 1: Configure Redis

To configure Redis into Laravel – you will need to install the package using the below command:

composer require predis/predis

Then after successful install configured Redis host, client, and database detail in the config/database.php file as follows:

‘redis’ => [
    ‘client’ => ‘predis’,
    ‘default’ => [
        ‘host’ => env(‘REDIS_HOST’, ‘127.0.0.1’),
        ‘password’ => env(‘REDIS_PASSWORD’, null),
        ‘port’ => env(‘REDIS_PORT’, 6379),
        ‘database’ => env(‘REDIS_DATABASE’, 0),
    ],
],

OR you can configure that from .env file also like below:

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
REDIS_DATABASE=0

To update the broadcast method as Redis in config/boradcasting.php,

‘default’ => env(‘BROADCAST_DRIVER’, ‘redis’),

OR you should update your broadcast driver to Redis in your .env file:

BROADCAST_DRIVER=redis

You will need to register the App\Providers\BroadcastServiceProvider for broadcasting events.

Also, do not forget to uncomment or add Illuminate\Broadcasting\BroadcastServiceProvider:class provider in the providers’ array of your config/app.php configuration file to allow you to register the broadcast authorization routes and callbacks.

Step 2: Create Event And Fire Event

We will need to create an event for broadcasting data. Run the below command to create an event file.

php artisan make:event ActionEvent

It will create a file look like below:

<?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;

class ActionEvent
{
  use Dispatchable, InteractsWithSockets, SerializesModels;

  /**
    * Create a new event instance.
    *
    * @return void
    */
  public function __construct()
  {
      //
  }

  /**
    * Get the channels the event should broadcast on.
    *
    * @return \Illuminate\Broadcasting\Channel|array
    */
  public function broadcastOn()
  {
      return new PrivateChannel(‘channel-name’);
  }
}

BroadcastOn method is responsible for returning the channels that the event should broadcast on. It should be instances of Channel, PrivateChannel, or PresenceChannel. And also, you can control your broadcast payload by using broadcastWith method to your event.

<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;

class ActionEvent implements ShouldBroadcastNow
{
  use Dispatchable, InteractsWithSockets, SerializesModels;

  public $actionId;
  public $actionData;

  /**
    * Create a new event instance.
    *
    * @author Author
    *
    * @return void
    */
  public function __construct($actionId, $actionData)
  {
      $this->actionId = $actionId;
      $this->actionData = $actionData;
  }

  /**
    * Get the channels the event should broadcast on.
    *
    * @author Author
    *
    * @return Channel|array
    */
  public function broadcastOn()
  {
      return new Channel(‘action-channel-one’);
  }

  /**
    * Get the data to broadcast.
    *
    * @author Author
    *
    * @return array
    */
  public function broadcastWith()
  {
      return [
          ‘actionId’ => $this->actionId,    
          ‘actionData’ => $this->actionData,

      ];
  }
}

Also, you can customize the broadcast name by defining a “broadcastAs” method on the event. If you modify your broadcast name using the “broadcastAs” method, you will need to register your listener with a leading character. You can also customize the queue by defining a “broadcastQueue” property in your event class. You can also add conditions for broadcast data by adding a “broadcastWhen.”

After that, we will fire the event to broadcast data.

event(new ActionEvent($actionId, $actionData));

Let’s take one example like we fired an event with a team score for a gaming app.

$actionId = “score_update”
$actionData = array(“team1_score” => 46)
event(new ActionEvent($actionId, $actionData));

Step 3: Install Required Packages

You will need to install “Node.js” and “redis-server” in your system or server. To install “redis-server,” you can use the below command:

npm install redis-server

You can verify redis is running correctly or not using the command “redis-cli ping.” It will return “pong” if Redis is installed and running.

You will need to install packages express, ioredis, socket.io, dotenv. So run the below command:

npm install express ioredis socket.io dotenv –save

Step 4: Configure Socket.IO

Now set up a socket server to listen and capture redis channel messages to broadcast, which are fired from events. Create a “server.js” file into the project root directory and add the below code.

‘use strict’;
var app = require(‘express’)();
var server = require(‘http’).Server(app);
var io = require(‘socket.io’)(server);
require(‘dotenv’).config();

var redisPort = process.env.REDIS_PORT;
var redisHost = process.env.REDIS_HOST;
var ioRedis = require(‘ioredis’);
var redis = new ioRedis(redisPort, redisHost);
redis.subscribe(‘action-channel-one’);
redis.on(‘message’, function (channel, message) {
  message  = JSON.parse(message);
  io.emit(channel + ‘:’ + message.event, message.data);
});

var broadcastPort = process.env.BROADCAST_PORT;
server.listen(broadcastPort, function () {
  console.log(‘Socket server is running.’);
});

  • We have created the redis object by connecting to the Redis server and port.
  • We need to subscribe to the channels on which data will be broadcast. We can subscribe to multiple channels.
  • When we fire an event, it will push data into Redis—using redis.on(‘message’) event system will get a message and channel name. Then using io.emit, it will broadcast data on a broadcastPort. Server.listen will listen to incoming requests from broadcastPort.
  • Now, you can run the script by calling the command “node server.js.” It will print the “Socket server is running.” into the console.

Step 5: Setup Websocket And Consume Data

After successful setup of broadcast data, we will set up a websocket channel and connect the publish URL on the page where we need to show real-time changes.

You will need to config publisher URL into your .env.

PUBLISHER_URL=http://127.0.0.1

Into your page, add code like below to get a message from the broadcast channel.

<div class=“container”>
  <h1>Team A Score</h1>
  <div id=“team1_score”></div>
</div>
<script src=“https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js”> </script>
<script>
  var sock = io(“{{ env(‘PUBLISHER_URL’) }}:{{ env(‘BROADCAST_PORT’) }}”);
  sock.on(‘action-channel-one:App\\Events\\ActionEvent’, function (data){
      //data.actionId and data.actionData hold the data that was broadcast
      //process the data, add needed functionality here
      var action = data.actionId;
      var actionData = data.actionData;
if(action == “score_update” && actionData.team1_score) {
          $(“#team1_score”).html(actionData.team1_score);
    }
});
</script>

The sock.on() will listen to a specific channel on the Websocket. We need to pass the socket channel name the same as we give in to the “server.js” script, e.g., channel-name: EventName. We can create multiple socks.on() calls to listen to different Websocket channels.

Conclusion

I hope it will help you make your real-time application like chatbots, games with live score updates, and broadcast some notice to all users. There are other methods for receiving broadcasts. You can also use the javascript library Laravel Echo for subscribing channels and receive messages from the broadcast.

At ZealousWeb, our recent project includes the implementation of this robust functionality. We used real-time broadcasting to build a game that involves participants and judges from across the world. It is a scheduled game that needs active participation from pre-listed candidates and works on a real-time basis.

Does that sound exciting to you?

It sure was for us to create the game!

You can always get in touch to know more about how we created certain functionalities or ask us, a Laravel development company, to create it for you! Alternatively, you can also hire a Laravel developer from us that’ll work only on your project.

FAQ

Why subscribe and broadcast in redis + socket io. is not working?

Case:  Can be prefix problem

Solution: Check your database.php OR .env file for REDIS_PREFIX. 

If REDIS_PREFIX is on and set, you will need to call your channel name with  laravel_database_ prefix. If APP_NAME is set in .env then prefix will be APP_NAME_database_. 

E.g., If your channel name is “action-channel-one,” then you will need to subscribe to the channel “laravel_database_action-channel-one.” If APP_NAME is defined as “TestApp” then subscribe to the channel “TestApp_database_action-channel-one.”

Why is broadcast on a private channel not working?

If you broadcast data on a private channel, you will need to add a “private-” prefix before the channel name. So your channel name will be like “private-action-channel-one.”

How to authenticate a private channel using redis and socket.io?

Define channel authorization rules in the routes/channels.php

Broadcast::channel(‘message.{userId}’, function ($user, $userId) {
//Authorization logic which should return a boolean
return $user->id === $userId;
});

Broadcast on channel will be defined like below:

public function broadcastOn() {
return new PrivateChannel(‘message.’.$this->broadcastUser->id);
}

Listening for event broadcast will be,

redis.subscribe(‘private-message.’ + window.APP.user);

Load more