Build a realtime counter with Laravel

Introduction

A realtime counter allows us to show the current active users without reloading the page. This paves a way to have better collaboration and brings dynamic feel to the application interface and a better usability.

Today, we will create a realtime counter system using Laravel and Pusher. With the release of Echo, Laravel has provided an out of the box solution for implementing realtime data synchronisation using event broadcasting. It is simple and we can get started in a matter of few minutes.

Setup an app on Pusher

We need to sign up on Pusher and create a new app.

counter-laravel-create-app

Install Laravel, Pusher SDK and Echo

First, we will grab a fresh copy of Laravel:

laravel new realtime-counter-laravel-pusher

This will install the latest version of the Laravel framework and download the necessary dependencies. Next, we will install the Pusher PHP SDK using Composer:

composer require pusher/pusher-php-server

Next, we will install the JavaScript dependencies:

npm install

Now, we need to install two Javascript libraries necessary for realtime event broadcasting: Laravel Echo and Pusher JS

npm install --save laravel-echo pusher-js

We will require some form of user authentication mechanism to demonstrate the functionality. Let us use the default authentication scaffolding provided by Laravel:

php artisan make:auth

Configuration

First, we need to set the APP_ID, APP_KEY, APP_SECRET and APP_CLUSTER in the environment file. We can get these details in our Pusher app dashboard:

1# .env
2
3BROADCAST_DRIVER=pusher
4
5PUSHER_APP_ID=your-pusher-app-id
6PUSHER_APP_KEY=your-pusher-app-key
7PUSHER_APP_SECRET=your-pusher-app-secret
8PUSHER_APP_CLUSTER=your-pusher-app-cluster

Next, we need to create a fresh Echo instance in our applications's JavaScript. We can do so at the bottom of our resources/assets/js/bootstrap.js file:

1import Echo from "laravel-echo"
2
3window.Echo = new Echo({
4    broadcaster: 'pusher',
5    key: 'your-pusher-app-key',
6    cluster: 'ap2',
7    encrypted: true
8});

Our application

The core feature of our app is the number of users active on this page. Whenever a user joins or leaves this page, the count of the online users will be automatically updated. The code is available on a Github repository for cloning and understanding purposes.

Online users

We will now show the number of users who are currently online on the website. This is a typical feature where we see the number of online users. Whenever a new user joins or leaves the page, the count is automatically updated.

We'll implement that with Echo and it is super simple. Let us go and fill out our listen method in the Example Vue component.

1listen() {
2    Echo.join('counter')
3        .here(users => this.count = users.length)
4        .joining(user => this.count++)
5        .leaving(user => this.count--);
6}

join is used when we want to join a presence channel and that is used to tell us who else is on the page. Presence channels are automatically private channels. We do need to authenticate them.

here gives us a list of users that are also present on the same page.

joining will be executed whenever a new user joins the channel or page in the above scenario.

leaving will be executed whenever a user leaves the channel.

Authorization

Every presence channel is a private channel. Laravel Echo will automatically call the specified authentication route. However, we still need to write the authentication logic which will actually authorize the user to listen to a particular channel.

Authorization logic is written in the routes/channels.php. The authorization logic for our counter channel is:

1Broadcast::channel('video', function ($user) {
2    return [
3        'id' => $user->id,
4        'name' => $user->name,
5    ];
6});

We are not going to return true or false. If the user is authenticated to listen on this presence channel we are going to return an array of data that we want to be returned to that callback in the listen method.

You can write the authentication logic as required for your application in the above callback and return null if authorization fails.

Vue Component

That's it! Now, whenever a new comment is created, it will be broadcast and we can listen using our presence channel.

Below is our Example component written using Vue.js

1<template>
2    <div class="container">
3        <div class="row">
4            <div class="col-md-8 col-md-offset-2">
5                <div class="panel panel-default">
6                    <div class="panel-heading">Realtime Counter</div>
7
8                    <div class="panel-body">
9                        <p class="lead text-center">Online Now</p>
10                        <h1 class="text-center">{{ this.count }}</h1>
11                    </div>
12                </div>
13            </div>
14        </div>
15    </div>
16</template>
17
18<script>
19    export default {
20        data() {
21            return {
22                count: 0
23            }
24        },
25        mounted() {
26            this.listen();
27        },
28        methods: {
29            listen() {
30                Echo.join('counter')
31                    .here(users => this.count = users.length)
32                    .joining(user => this.count++)
33                    .leaving(user => this.count--);
34            }
35        }
36    }
37</script>

Below is the demonstration where the count of users present on the page is updated automatically when a user leaves or joins the page.

counter-laravel-demo

Conclusion

In this article, we have covered how to create a realtime counter using Laravel and Pusher. We have covered the configuration options necessary to get started, and the example above should help you fill in the gaps and give an overview of some of the other configuration options available to you.