While this tutorial has content that we believe is of great benefit to our community, we have not yet tested or edited it to ensure you have an error-free learning experience. It's on our list, and we're working on it! You can help us out by using the "report an issue" button at the bottom of the tutorial.

Many web applications include an in-app notification system that will notify you instantly when someone carries out an action related to you or your account. On Facebook, you will be notified when someone likes your status, or when someone comments on your profile. This tutorial will guide you through replicating this functionality by creating a web-based notification system using Laravel and Pusher.

Prerequisites

To follow this tutorial you need to have PHP and Laravel installed on your machine, along with a Pusher account.

What we would be building

After this tutorial we would demonstrate how we can have a small web application show notifications using Laravel and Pusher. It would be similar to how websites like Facebook show notifications. Here is a preview of what we would be building:

Animated GIF showing a browser with live notifications

Setting up your Pusher application

Create a Pusher account, if you have not already, and then set up your application as seen in the screenshot below.

how-to-create-web-notifications-using-laravel-and-pusher-1

Setting up your Laravel application

Create a new Laravel application by running the command below in your terminal:

  • laravel new laravel-web-notifications

After that, install the Pusher PHP SDK using Composer. Run the following command:

  • composer require pusher/pusher-php-server

When Composer is finished, the next step is to configure Laravel to use Pusher as its broadcast driver. To do this, open the .env file that is in the root directory of your Laravel installation. Update the values to match with the configuration below:

    PUSHER_APP_ID=322700
    BROADCAST_DRIVER=pusher

    // Get the credentials from your pusher dashboard
    PUSHER_APP_ID=XXXXX
    PUSHER_APP_KEY=XXXXXXX
    PUSHER_APP_SECRET=XXXXXXX

Important Note: If you’re using the EU or AP Cluster, make sure to update the options array in your config/broadcasting.php config since Laravel defaults to using the US Server. You can use all the options the Pusher PHP Library supports.

Open config/app.php and uncomment the App\Providers\BroadcastServiceProvider::class.

Creating our Laravel and Pusher application

Now that the configuration steps are complete it is time to create the application. First create an Event class that will broadcast to Pusher from our Laravel application. Events can be fired from anywhere in the application.

  • php artisan make:event StatusLiked

This will create a new StatusLiked class in the app/Events directory. Open the contents of the file and update to the following below:

<?php

namespace App\Events;

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

class StatusLiked 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} liked your status";
    }

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

The ShouldBroadcast interface tells Laravel that this event should be broadcast using whatever driver is set in the configuration file.

There is also a constructor that accepts two parameters, username and verb. These variables are assigned to class properties named the same way. It is important to set the visibility of the properties to public; if you don’t, the property will be ignored.

Lastly, the channel name to broadcast on is set.

Creating the application views

This tutorial will use a single view with a navigation bar and a notification icon. The icon will be updated when new notifications are available without the need to refresh the page. The notifications are ephemeral in this tutorial by design; you can extend the functionality and make it last longer after the page reloads if you like.

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>Demo Application</title>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="/css/bootstrap-notifications.min.css">
    <!--[if lt IE 9]>
      <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
      <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
  </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 navigation</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 all as read</a>
                  </div>
                  <h3 class="dropdown-toolbar-title">Notifications (<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="#">Timeline</a></li>
            <li><a href="#">Friends</a></li>
          </ul>
        </div>
      </div>
    </nav>

    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
    <script src="//js.pusher.com/3.1/pusher.min.js"></script>
    <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>

    <script type="text/javascript">
      var notificationsWrapper   = $('.dropdown-notifications');
      var notificationsToggle    = notificationsWrapper.find('a[data-toggle]');
      var notificationsCountElem = notificationsToggle.find('i[data-count]');
      var notificationsCount     = parseInt(notificationsCountElem.data('count'));
      var notifications          = notificationsWrapper.find('ul.dropdown-menu');

      if (notificationsCount <= 0) {
        notificationsWrapper.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('status-liked');

      // Bind a function to a Event (the full Laravel class)
      channel.bind('App\\Events\\StatusLiked', 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">Extra description can go here</p-->
                  <div class="notification-meta">
                    <small class="timestamp">about a minute ago</small>
                  </div>
                </div>
              </div>
          </li>
        `;
        notifications.html(newNotificationHtml + existingNotifications);

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

This a lot of code to go over, but the important parts are the Javascript portions. The Pusher javascript library is included, and then the javascript block that pushes notifications. These are the important snippets in the javascript block:

// Enable pusher logging - don't include this 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('status-liked');

// Bind a function to a Event (the full Laravel class)
channel.bind('App\\Events\\StatusLiked', function(data) {
    // this is called when the event notification is received...
});

Note: : By default Laravel will broadcast the event using the event’s class name. However, you may customize the broadcast name by defining a broadcast as method on the event:

public function broadcastAs() {
  return 'event-name';
}

The code above initializes the Pusher JS library and subscribes to a channel. It then sets a callback to call when the event broadcasted is received on that channel.

Testing the set up

Finally to test this set up, create a route that manually calls the event. If everything works as expected, a new notification will appear anytime the route is reached. Let’s add the new route:

Route::get('test', function () {
    event(new App\Events\StatusLiked('Someone'));
    return "Event has been sent!";
});

Now start a PHP server using Laravel to test that the code works:

  • $ php artisan serve

Conclusion

In this tutorial you leveraged the power of Pusher to create a modern web notifications system with relatively little code. This functionality is a small example of the many things that can be done using Pusher. This example is one of many possible tools that you can build using Pusher.

The code is available on GitHub.

0 Comments

Creative Commons License