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.
To follow this tutorial you need to have PHP and Laravel installed on your machine, along with a Pusher account.
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:
Create a Pusher account, if you have not already, and then set up your application as seen in the screenshot below.
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
.
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.
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.
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
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.
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.
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!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
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 ?