Back to Blog
LaravelPHPJune 23, 20264 min read

Mastering Laravel Database Notifications: A Beginner’s Guide

Master Laravel database notifications to store and retrieve user alerts efficiently. Learn how to implement this powerful feature in your PHP application.

LaravelPHPNotificationsDatabaseWeb DevelopmentTutorial

Last month, I was debugging an issue where users kept missing critical updates because we relied entirely on email notifications. I realized that if a user didn't check their inbox, the alerts effectively didn't exist, so I pivoted our design to include persistent laravel database notifications directly within the dashboard.

If you’re building a feature-rich application, you need a way to track user activity, and storing these alerts in your laravel database is the most reliable way to ensure nothing gets lost.

Setting Up Your Notification Table

Before you can send your first alert, you need a place to store them. Laravel makes this incredibly easy with a built-in migration command. Run this in your terminal:

Bash
php artisan notifications:table
php artisan migrate

This creates a notifications table. It’s a polymorphic table, meaning it can store notifications for any model (usually your User model) without needing a separate table for every alert type. It’s elegant, clean, and saves you from writing custom schema migrations.

Creating a Notification Class

To generate a notification, use the artisan command:

Bash
php artisan make:notification OrderShipped

Open the newly created file in app/Notifications. You'll see a via method. This is where you tell Laravel how to deliver the notification. For our purpose, we want to return ['database'].

PHP
public function via($notifiable)
{
    return ['database'];
}

Now, define the toArray method. This is the data that gets serialized into the data column of your notifications table.

PHP
public function toArray($notifiable)
{
    return [
        'order_id' => $this->order->id,
        'message' => 'Your order #' . $this->order->id . ' has shipped!',
    ];
}

If you are just getting started with multi-channel alerts, check out my previous post on Laravel Notifications: A Beginner’s Guide to Multi-Channel Alerts to see how you can extend this to email or Slack later.

Retrieving and Displaying Alerts

Once you send a notification, it sits in your database waiting to be fetched. You can access these via the notifications relationship on your model.

In your controller or view, you can pull them like this:

PHP
$user = auth()->user();

foreach ($user->unreadNotifications as $notification) {
    echo $notification->data['message'];
}

I once tried to manually query the table using DB::table('notifications')->where(...). Don't do that. The Notifiable trait on your User model provides all the helper methods you need, like markAsRead() or unreadNotifications, which are much safer. If you're doing complex operations, always remember that Laravel database transactions: Mastering atomic operations with DB::transaction are your best friend to keep data consistent.

Why Database Notifications?

When I first started, I thought about building a custom Alerts table. It seemed easy until I had to handle read/unread states, timestamps, and polymorphic relationships. By sticking to the framework’s native implementation, I saved about two days of development time.

However, there is one catch: the data column is a JSON field. While this is flexible, it means you can't easily index specific fields inside the JSON for complex filtering. If you’re building a massive notification center with millions of rows, you might eventually need to denormalize your schema. For 99% of projects, though, the standard setup is more than enough.

Pro-Tips for Better UX

  1. Mark as Read: Don't forget to provide an endpoint to clear the notification. Calling $user->unreadNotifications->markAsRead() is the standard way to handle this.
  2. Batching: If you are sending many notifications at once, use a background job. Sending them synchronously during a request cycle will spike your response time by around 150ms-200ms depending on your database latency.
  3. Frontend Integration: I usually expose an API endpoint that returns the user's unread notifications as JSON, then fetch them via Alpine.js or Vue on the frontend to update a "bell" icon in the navbar.

I'm still tinkering with how to handle notification expiration—right now, I just run a scheduled task to delete notifications older than 30 days. It keeps the table lean and ensures the app stays fast. If you find yourself needing to automate parts of this process, look into Mastering Laravel Observers: A Beginner’s Guide to Automation to trigger alerts whenever a model changes.

What’s your biggest struggle with user alerts? Are you worried about database bloat or just getting the UI right? Start simple, get the data flowing, and iterate from there.

Similar Posts