Codementor Events

Implementing real-time notifications in Laravel using Pusher

Published Mar 26, 2018
Implementing real-time notifications in Laravel using Pusher

Real time notifications, Sound interesting isn't it ? Who wants to refresh page, when you informed about the on-going or completed process.
687474703a2f2f692e696d6775722e636f6d2f33516d4565566c2e676966.gif

Let's do this.

Configuration Part

You will need a Pusher account. Open and Sign up, they always have a free plan for developers. Follow the steps.

Step: Install laravel by running following command in your terminal.

laravel new web-notify-demo

Step: Create pusher application.
Screen Shot 2018-03-24 at 1.19.47 PM.png
Select JavaScript as front-end tech and Laravel/PHP as back-end tech.

Step: Go to .env tab in next screen of pusher, Copy credentials and
Paste in your .env file. Your .env file should look like:

BROADCAST_DRIVER=pusher
PUSHER_APP_ID="33333333" 
PUSHER_APP_KEY="1c097031061ee8684233"
PUSHER_APP_SECRET="c50176dc941df274c813"

Step: Install laravel & pusher dependancy.

composer require pusher/pusher-php-server

Step: Open config/app.php and uncomment following line.

App\Providers\BroadcastServiceProvider::class

Now, We done with the configuration, Let's work on notification module.

Implementation

Step: First we would create an Event Class that would broadcast to pusher from anywhere in the application. Laravel Events can be fired from anywhere in the application.

php artisan make:event UserCreated

This will create a new UserCreated class in app/events directory. Open it and update in following way.

<?php
namespace App\Events;

use Illuminate\Queue\SerializesModels;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

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

    public $username;

    public $message;

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct($username)
    {
        $this->username = $username;
        $this->message  = "{$username} has created a new user.";
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return Channel|array
     */
    public function broadcastOn()
    {
        return ['user-created'];
    }
}

ShouldBroadcast is an interface, This tell laravel this tells Laravel that this event should be broadcasted using whatever driver we have set in the configuration file. In our case it is pusher, Which we enabled in .env file "BROADCAST_DRIVER=pusher".

Step: I'll try to make things simple, Below code will create a navbar with the notification icon. Notifications will be displayed whenever event is fired, In our case when new user is created.
Open the welcome.blade.php file and replace it with the HTML below.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Notification App</title>
    <!-- Latest compiled and minified CSS -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
  </head>
  <body>
    <nav class="navbar navbar-inverse">
      <div class="container-fluid">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-9" aria-expanded="false">
            <span class="sr-only">Toggle</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Demo App</a>
        </div>

        <div class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
            <li class="dropdown dropdown-notifications">
              <a href="#notifications-panel" class="dropdown-toggle" data-toggle="dropdown">
                <i data-count="0" class="glyphicon glyphicon-bell notification-icon"></i>
              </a>

              <div class="dropdown-container">
                <div class="dropdown-toolbar">
                  <div class="dropdown-toolbar-actions">
                    <a href="#">Mark as read</a>
                  </div>
                  <h3 class="dropdown-toolbar-title">Noti (<span class="notif-count">0</span>)</h3>
                </div>
                <ul class="dropdown-menu">
                </ul>
                <div class="dropdown-footer text-center">
                  <a href="#">View All</a>
                </div>
              </div>
            </li>
            <li><a href="#">Other 1</a></li>
            <li><a href="#">Other 2</a></li>
          </ul>
        </div>
      </div>
    </nav>

    <script   src="https://code.jquery.com/jquery-2.1.4.min.js"   integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw="   crossorigin="anonymous"></script>
    <script src="//js.pusher.com/3.1/pusher.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

    <script type="text/javascript">
      var notiWrapper   = $('.dropdown-notifications');
      var notiToggle    = notiWrapper.find('a[data-toggle]');
      var notiCountElem = notiToggle.find('i[data-count]');
      var notiCount     = parseInt(notiCountElem.data('count'));
      var notifications          = notiWrapper.find('ul.dropdown-menu');

      if (notiCount <= 0) {
        notiWrapper.hide();
      }

      // Enable pusher logging - don't include this in production
      // Pusher.logToConsole = true;

      var pusher = new Pusher('API_KEY_HERE', {
        encrypted: true
      });

      // Subscribe to the channel we specified in our Laravel Event
      var channel = pusher.subscribe('user-created');

      // Bind a function to a Event (the full Laravel class)
      channel.bind('App\\Events\\UserCreated', function(data) {
        var existingNotifications = notifications.html();
        var avatar = Math.floor(Math.random() * (71 - 20 + 1)) + 20;
        var newNotificationHtml = `
          <li class="notification active">
              <div class="media">
                <div class="media-left">
                  <div class="media-object">
                    <img src="https://api.adorable.io/avatars/71/`+avatar+`.png" class="img-circle" alt="50x50" style="width: 50px; height: 50px;">
                  </div>
                </div>
                <div class="media-body">
                  <strong class="notification-title">`+data.message+`</strong>
                  <!--p class="notification-desc">Some extra text</p-->
                  <div class="notification-meta">
                    <small class="timestamp">a second ago</small>
                  </div>
                </div>
              </div>
          </li>
        `;
        notifications.html(newNotificationHtml + existingNotifications);

        notiCount += 1;
        notiCountElem.attr('data-count', notiCount);
        notiWrapper.find('.notif-count').text(notiCount);
        notiWrapper.show();
      });
    </script>
  </body>
</html>

This looks like hell lot of code if you're not familliar with bootstrap. Let me explain what I've included.

Pusher's JavaScript library and following JavaScript code

// This enables pusher logging, Don't include in production.
// Pusher.logToConsole = true;

// Initiate the Pusher JS library
var pusher = new Pusher('API_KEY_HERE', {
    encrypted: true
});

// Subscribe to the channel we specified in our Laravel Event
var channel = pusher.subscribe('user-created');

// Bind a function to a Event (the full Laravel class)
channel.bind('App\\Events\\UserCreated', function(data) {
    // you can put more functions here, This will be called when event recieved.
});

That's it. Let's test our work.

Testing our application

Let's create a route that manually calls event. If all goes well, than we will get a notification "Yuvraj has created a new user".

Route::get('fire', function () {
    event(new App\Events\UserCreated('Yuvraj'));
    return "Event fired!";
});

Let's serve.

$ php artisan serve

That's It
Play around with the application, try to get best out of it. There can be many usecases of Pusher. Keep your browser web developer tool open and code on.

Discover and read more posts from Yuvrajsinh Jhala
get started
post commentsBe the first to share your opinion
Show more replies