This article was originally written by Funke Faith Olasupo on the Honeybadger Developer Blog.
When building applications, notifications are essential because they improve user experience and interaction. It would be helpful if you frequently alerted users to various changes or activities while they use applications. It can involve sending an SMS about their login activity for security purposes or email notifications when an order status changes. Often, these notifications only offer a brief explanation of the state changes.
Laravel supports several delivery channels for sending notifications, including emails, SMS, and Slack. Additionally, notifications may be kept in a database and displayed on your Web interface. Here are a few things you'll learn in this guide:
- What are notifications?
- Notification Channels supported by Laravel.
- How to use live database notifications in Laravel.
- How to use email notifications in Laravel.
- Other Laravel-supported notification delivery channels.
Laravel Notifications
Notifications can be considered brief, direct messages sent to users to inform them of important information and events or to prompt a response in the application. Ideally, they keep users updated and increase user engagement. Laravel provides support for sending notifications via a variety of channels. By default, it includes mail, Slack, database, broadcast, and Vonage channels.
By using the Laravel Artisan command, you can quickly create notifications. You can also customize the notification's details.
Laravel's Notification Channels
Laravel allows you to select from various notification channels to send notifications in your application. You can use more than one channel.
Mail — These notifications are sent as an email to users.
SMS — Users receive these SMS notifications on their mobile phones.
Database — These notifications are stored in the database, and you can display them to the user with a custom UI.
Slack — These notifications are sent to Slack channels.
Community-Driven Notifications
Check out the community-driven Laravel Notification Channels website if you want to use other channels, such as Telegram.
You can also decide to create drivers to deliver notifications via other channels.
In this tutorial, we'll build a Laravel application that sends notifications via email and database channels. The source code for the final application is available on GitHub.
How to Send Database Notifications
The notifications are kept in a database table when sent via the database channel. The type of notification and the JSON data that identifies the notification are both included in this table.
Create a New Laravel Project
You can create a new Laravel project via the Composer command or the Laravel installer:
bash
laravel new project_name
//Or
composer create-project laravel/laravel project_name
This will create a new Laravel application in a new directory named project_name.
Connect to Your Database
Here is an article I wrote that explains how to connect a Laravel Application to a MySQL database. If you have a different database, make sure to connect it appropriately.
Set Up a Default Authentication Scaffold
Laravel Auth provides a prebuilt authentication UI and functionality to interact with. Install the Laravel UI package with this command:
composer require laravel/ui
Then create a bootstrap auth scaffold. A bootstrap authentication scaffold provides a default UI and basic authentication for registration and login in Laravel. You can install it with the Artisan
command:
php artisan ui bootstrap --auth
Next, install the npm
packages to generate the css
and js
files and run the environment.
npm install
npm run dev
Finally, run your migrations to create your database tables with this command:
php artisan migrate
Run the Application
Run this Artisan
command to serve the project:
php artisan serve
The application is served on port 8000
by default, and if you visit http://localhost:8000/
on your browser, you should view this landing page with the login
and register
options at the top right.
Upon successful registration or login, you can view your dashboard. All these basic authentication processes and UI are handled by the laravel/ui
package installed earlier.
Create a Notifications Table
You need to create a database table to contain all your notifications. It can be queried anytime to display notifications to the user interface. To generate a migration with a proper notification table schema, you may use this Artisan
command:
php artisan notifications:table
This creates a create_notifications_table.php in the database/migrations directory, which defines the schema of the notifications table. Now you can migrate to your database by running the following:
php artisan migrate
Generating Notifications
Each notification in Laravel is represented by a single class, normally stored in the app/Notifications directory. It will be generated when you run the make:notification
Artisan command:
php artisan make:notification DepositSuccessful
This generates a DepositSuccessful.php file with a new notification class in the app/Notifications directory. This class includes a via()
method that specifies the channel and body message-building methods to assist in formatting the notification data for the selected channel.
The notification class should have a defined toDatabase
or toArray
function. This method should return a simple PHP array after receiving a $notifiable
entity. The returned array will be stored in the data
column of your notifications table after being encoded as JSON.
Formatting Database Notifications
You want to notify users whenever they make a successful deposit in the app of the amount they deposited.
Update the __construct()
method in the DepositSuccessful.php file to match this example:
protected $amount;
public function __construct($amount)
{
$this->amount=$amount;
}
Now the deposit amount has been injected in the construct()
method, so it can be used in generating mail messages.
Now, you need to specify the notification channel to use by updating the via()
method:
public function via($notifiable)
{
return ['database'];
}
Next, update the toArray()
or toDatabase()
method with the details of the notification.
You must define either a toDatabase()
or toArray()
method, and it should return a simple PHP array stored in the data
column of the notifications table.
public function toArray($notifiable)
{
return [
'data' =>' Your deposit of '. $this->amount.' was successful'
];
}
The
toArray()
is used by both the database broadcast channel. If you want to use both channels in the app with different array representations, you should definetoDatabase()
andtoArray()
. However,toArray()
is the default.
Add the Notifiable Trait
Laravel notification offers two methods to send notifications. It includes the Notifiable
trait or Notification
facade. In this tutorial, we will focus on the Notifiable trait.
By default, Laravel includes the Notifiable trait in the app/Models/User
model. It should match this example:
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
.
.//Other model definitions
.
}
Set Up the Deposit Model and Migration
First, create the model and database migration simultaneously by running the command below:
php artisan make:model Deposit -m
This creates a Model file called Deposit.php in the app/Models directory and a Migration file called create_deposits_table.php in the database/migrations directory.
Update Deposit.php by adding the code below to the top of the file, which enables Model mass assignment.
protected $guarded = [];
Then, update the up()
method in the create_deposits_table.php migration file with deposit details to be stored, as shown in the example below:
public function up()
{
Schema::create('deposits', function (Blueprint $table) {
$table->id();
$table->string('amount');
$table->foreignId('user_id')->references('id')->on('users')->constrained()->onDelete('cascade')->onUpdate('cascade');
$table->timestamps();
});
}
Then, run your migrations to the database again.
php artisan migrate
Set Up Controller
It would be best if you defined the logic for making a deposit and sending the notification after a successful deposit in the controller.
To create the controller, run this Artisan command:
php artisan make:controller DepositController
A new file DepositController.php is created in the app/Http/Controllers directory.
With the file created, add the import
statements below to import the classes that the controller will use:
use App\Models\Deposit;
use App\Models\User;
use App\Notifications\DepositSuccessful;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
Add a _construct()
method to declare the auth
middleware, which allows only authenticated users to make a deposit.
public function __construct()
{
$this->middleware('auth');
}
Define a deposit()
method to include logic for making a deposit and sending a successful deposit notification.
public function deposit(Request $request){
$deposit = Deposit::create([
'user_id' =>Auth::user()->id,
'amount' => $request->amount
]);
User::find(Auth::user()->id)->notify(new DepositSuccessful($deposit->amount));
return redirect()->back()->with('status','Your deposit was successful!');
}
Notifications are sent using either the notify()
method from the Notifiable trait or Notification facade. The facade is useful when sending notifications to multiple entities, such as a collection of users. Although we use notify()
for this guide, here is an example of using Notification
facade.
$users = User::all();
Notification::send($users, new DepositSuccessful($deposit->amount));
Note: The Notifiable trait has already been imported into the User model. You can import it into any model you need to send notifications.
Set Up the Routes
You will add a new route in routes/web.php.
Route::post('/deposit', [App\Http\Controllers\DepositController::class,'deposit'])->name('deposit');
Modify the View
Add a basic form to the homepage for a user to deposit resources\views\home.blade.php directory.
<form method="POST" action="{{ route('deposit') }}">
@csrf
<h5 class="text-center mb-3">Make A Deposit</h5>
<div class="row mb-3">
<label for="amount" class="col-md-4 col-form-label text-md-end">{{ __('Amount') }}</label>
<div class="col-md-6">
<input id="amount" type="number" class="form-control @error('amount') is-invalid
@enderror" name="amount" value="{{ old('amount') }}" required autocomplete="amount" autofocus>
@error('amount')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
@enderror
</div>
</div>
<div class="row mb-0">
<div class="col-md-8 offset-md-4">
<button type="submit" class="btn btn-primary">
{{ __('Deposit') }}
</button>
</div>
</div>
</form>
Awesome job👍! Let's make things more interesting by including a bell notification on the navbar showing the number of unread notifications. You can also display both read and unread notifications.
Laravel's Notifiable
trait provides another excellent feature that can help you track both read and unread notifications. You can also mark a notification as read or delete a notification entirely.
Update the Controller, Route, and View with the MarkasRead Feature
Define a new method, markAsRead()
in the DepositController.php to mark all unread notifications as read.
public function markAsRead(){
Auth::user()->unreadNotifications->markAsRead();
return redirect()->back();
}
Now, add the corresponding route to the routes/web.php .
Route::get('/mark-as-read', [App\Http\Controllers\DepositController::class,'markAsRead'])->name('mark-as-read');
You will update the resources\views\layouts\app.blade.php with a few changes for this feature.
First, include this CDN link to Font Awesome in the blade file to enable you to use the bell icon.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css" integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A==" crossorigin="anonymous" referrerpolicy="no-referrer" />
Now, add this example before the full name and logout dropdown immediately after the else
statement.
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link " href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
<i class="fa fa-bell"></i>
<span class="badge badge-light bg-success badge-xs">{{auth()->user()->unreadNotifications->count()}}</span>
</a>
<ul class="dropdown-menu">
@if (auth()->user()->unreadNotifications)
<li class="d-flex justify-content-end mx-1 my-2">
<a href="{{route('mark-as-read')}}" class="btn btn-success btn-sm">Mark All as Read</a>
</li>
@endif
@foreach (auth()->user()->unreadNotifications as $notification)
<a href="#" class="text-success"><li class="p-1 text-success"> {{$notification->data['data']}}</li></a>
@endforeach
@foreach (auth()->user()->readNotifications as $notification)
<a href="#" class="text-secondary"><li class="p-1 text-secondary"> {{$notification->data['data']}}</li></a>
@endforeach
</ul>
</li>
This will result in a bell icon with a badge count of the unread notifications before the full name and logout dropdown on the dashboard. It also has a dropdown of all notifications, with the unread ones at the top. The dropdown also has an option to mark all notifications as read so that the badge count returns to 0 (which means there are no unread notifications).
Amazing job🤩! At this point, you can proceed to test by making a deposit to view how your notifications display on the dashboard after it's successful.
How to Send Email Notifications
However, let's go a bit further and include email notifications. When a deposit is made, we want to display notifications in the dashboard and send an email to the user.
Update .env
Mail Configurations
You need to update these environment variables with valid mailer credentials that your app will need to send emails to users.
MAIL_MAILER=
MAIL_HOST=
MAIL_PORT=
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=
MAIL_FROM_ADDRESS=
MAIL_FROM_NAME="${APP_NAME}"
Formatting Mail Notifications
In the DepositSuccessful
notification class you created earlier, update the via()
method to include email.
public function via($notifiable)
{
return ['mail','database'];
}
Afterward, define the toMail()
method with the mail messages. This method should return an Illuminate/Notifications/Messages/MailMessage
instance after receiving a $notifiable
entity.
You can now build email messages with the help of a few simple methods provided by the MailMessage
class. A "call to action" and lines of text are possible in mail messages.
public function toMail($notifiable)
{
$url = url('/home');
return (new MailMessage)
->greeting('Hello,')
->line('Your deposit of '. $this->amount. ' was successful.')
->action('View dashboard', url('/home'))
->line('Thank you for using our application!');
}
Small transactional emails can be formatted quickly and easily using these methods provided by the MailMessage
object. A beautiful, responsive HTML email template with a plain-text counterpart will be generated from the message components by the mail channel. In this example, we supplied a call to action(button), a line of text, and a greeting.
Hurrah 😎! We are done building 👍. Now, let's perform some testing and see if it works.
Testing
If you make a successful deposit, you will get a notification in your dashboard that looks like this:
Notice that the badge number only counts the unread notifications. However, the dropdown lists all notifications, starting with the unread ones. If you decide to mark all as read
, it refreshes, and your notification badge count returns to 0 because you have read all the current notifications.
You will also receive a mail notification that looks like this:
Notice that the greeting, line of text, and call to action (button) have been formatted to a responsive email template.
Conclusion
In this article, you have gained an in-depth understanding of Laravel Notifications. It is a broad concept, but this can be a great practical guide. Check out the official Laravel documentation to learn more about Laravel Notifications. It provides various flexible options, and you can customize these channels to tailor your application needs or create your drivers to deliver notifications via other channels. The code for this project is open-source and available on GitHub.
I am open to questions, contributions, and conversations on better ways to implement notifications, so please comment on the repository or DM me @twitter.
Thanks for reading🤝.
Top comments (3)
Great Article 👏
Thanks!