Tutorial

How To Create Web Notifications Using Laravel and Pusher Channels

Published on December 12, 2019
Default avatar

By Neo Ighodaro

How To Create Web Notifications Using Laravel and Pusher Channels

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking 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:

  1. laravel new laravel-web-notifications

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

  1. 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.

  1. 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:

  1. $ 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.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Neo Ighodaro

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
1 Comments


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

its a good and perfect tutorial. but im facing 2 problems… 1. how to erase all notifications with count when user click view all messages. 2. when i page refresh all notification is gone why ?

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Get our biweekly newsletter

Sign up for Infrastructure as a Newsletter.

Hollie's Hub for Good

Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

Become a contributor

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

Welcome to the developer cloud

DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

Learn more
DigitalOcean Cloud Control Panel