csouza/notification-management

Laravel package for managing user notification preferences across multiple channels

Installs: 1

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/csouza/notification-management

v1.0.1 2025-11-21 15:46 UTC

This package is auto-updated.

Last update: 2025-12-21 15:58:03 UTC


README

Latest Version on Packagist Total Downloads GitHub Tests Action Status GitHub Code Style Action Status

A powerful Laravel package that allows users to manage their notification preferences across multiple channels. Let your users decide how they want to be notified!

Features

User Preferences: Let users choose which channels they want to receive notifications through
📱 Multiple Channels: Support for Laravel native channels (mail, database, broadcast) and custom channels
🔧 Easy Integration: Simple trait to add to your User model
📊 Notification Logging: Track all sent notifications
🎯 Type-based Control: Different preferences per notification type
🚀 API Ready: Built-in REST API for managing preferences
🔐 Built-in Notifications: Includes user.logged notification out of the box

Installation

Install the package via composer:

composer require csouza/notification-management

Publish the config and migrations:

php artisan vendor:publish --tag=notification-management-config
php artisan vendor:publish --tag=notification-management-migrations

Run the migrations:

php artisan migrate

Configuration

Add the trait to your User model:

use Csouza\NotificationManagement\Traits\HasNotificationPreferences;

class User extends Authenticatable
{
    use HasNotificationPreferences;
}

Usage

Managing User Preferences

// Enable a channel for a notification type
$user->enableNotificationChannel('order.shipped', 'mail');
$user->enableNotificationChannel('order.shipped', 'database');

// Disable a channel
$user->disableNotificationChannel('order.shipped', 'sms');

// Check if user wants to receive via a channel
if ($user->wantsNotificationVia('order.shipped', 'mail')) {
    // User wants email notifications for shipped orders
}

// Get all active channels for a notification type
$channels = $user->getActiveChannelsFor('order.shipped');
// Returns: ['mail', 'database']

// Set bulk preferences
$user->setNotificationPreferences([
    'order.shipped' => ['mail' => true, 'sms' => false],
    'order.delivered' => ['mail' => true, 'database' => true],
]);

Creating Notifications

Use the UsesNotificationPreferences trait in your notification classes to automatically respect user preferences:

use Csouza\NotificationManagement\Traits\UsesNotificationPreferences;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\MailMessage;

class OrderShipped extends Notification
{
    use UsesNotificationPreferences;

    /**
     * Define the notification type identifier
     */
    protected string $notificationType = 'order.shipped';

    public function __construct(
        protected Order $order
    ) {}

    /**
     * No need to define via() - the trait handles it automatically
     * based on user preferences!
     */

    public function toMail(object $notifiable): MailMessage
    {
        return (new MailMessage)
            ->subject('Your order has been shipped!')
            ->line('Your order #'.$this->order->id.' is on its way!')
            ->action('Track Order', url('/orders/'.$this->order->id));
    }

    public function toDatabase(object $notifiable): array
    {
        return [
            'order_id' => $this->order->id,
            'message' => 'Your order has been shipped',
        ];
    }
}

The trait automatically:

  • ✅ Checks user preferences for the notification type
  • ✅ Returns only enabled channels
  • ✅ Respects default configurations
  • ✅ No need to manually implement the via() method!

Advanced: Limiting Channels

// Force specific channels (ignores user preferences)
class SecurityAlert extends Notification
{
    use UsesNotificationPreferences;
    
    protected string $notificationType = 'security.alert';
    protected array $forceChannels = ['database']; // Always use database
}

// Limit allowed channels (intersects with user preferences)
class MarketingEmail extends Notification
{
    use UsesNotificationPreferences;
    
    protected string $notificationType = 'marketing.promo';
    protected array $allowedChannels = ['mail']; // Only allow email, filter out others
}

Sending Notifications

The package integrates seamlessly with Laravel's notification system:

use App\Notifications\OrderShipped;
use Csouza\NotificationManagement\Facades\NotificationManager;

// Send notification respecting user preferences
NotificationManager::send($user, 'order.shipped', OrderShipped::class, [
    'order_id' => $order->id,
    'tracking_code' => $order->tracking_code,
]);

// Or using the notification instance
NotificationManager::send($user, 'order.shipped', new OrderShipped($order));

// Send by type (requires notification_types config)
NotificationManager::sendByType($user, 'order.shipped', [
    'order_id' => $order->id,
]);

Automatic Event-to-Notification Mapping 🚀

New! Automatically send notifications when Laravel events are fired, without creating listener classes:

// config/notification-management.php
'event_notifications' => [
    // Simple: property extraction
    \Illuminate\Auth\Events\Login::class => [
        'notification_type' => 'user.logged',
        'notifiable' => 'user', // $event->user
    ],
    
    // Nested: dot notation
    \App\Events\OrderShipped::class => [
        'notification_type' => 'order.shipped',
        'notifiable' => 'order.user', // $event->order->user
        'data' => fn($event) => ['order_id' => $event->order->id],
    ],
    
    // Advanced: closure with condition
    \App\Events\PaymentFailed::class => [
        'notification_type' => 'payment.failed',
        'notifiable' => 'user',
        'condition' => fn($event) => $event->attempts >= 3,
    ],
    
    // Multiple: notify collection of users
    \App\Events\PostPublished::class => [
        'notification_type' => 'post.published',
        'notifiable' => fn($event) => $event->post->subscribers,
    ],
],

Benefits:

  • ✅ No listener classes needed
  • ✅ Configuration-driven
  • ✅ Supports closures for complex logic
  • ✅ Conditional notifications
  • ✅ Multiple notifiables (collections)

See Event Notifications Documentation for complete guide.

Built-in User Login Notification

The package includes a ready-to-use notification for user logins. Simply register the listener:

// app/Providers/EventServiceProvider.php
use Illuminate\Auth\Events\Login;
use Csouza\NotificationManagement\Listeners\SendUserLoggedNotification;

protected $listen = [
    Login::class => [
        SendUserLoggedNotification::class,
    ],
];

Now users will automatically receive notifications when they log in, including:

  • IP Address
  • Browser/User Agent
  • Location (if configured)
  • Login timestamp

Users can control how they receive these notifications:

// Enable email notifications for logins
$user->enableNotificationChannel('user.logged', 'mail');

// Disable SMS notifications for logins
$user->disableNotificationChannel('user.logged', 'sms');

See docs/user-logged-notification.md for full documentation.

Custom Channels

Register custom channels in your AppServiceProvider:

use Csouza\NotificationManagement\Managers\ChannelRegistry;

public function boot()
{
    $registry = app(ChannelRegistry::class);
    
    $registry->register('sms', \App\Channels\SmsChannel::class);
    $registry->register('telegram', \App\Channels\TelegramChannel::class);
    $registry->register('slack', \App\Channels\SlackChannel::class);
}

Or add them to config/notification-management.php:

'channels' => [
    'sms' => [
        'driver' => \App\Channels\SmsChannel::class,
        'enabled' => true,
        'description' => 'SMS notifications',
    ],
    'telegram' => [
        'driver' => \App\Channels\TelegramChannel::class,
        'enabled' => true,
        'description' => 'Telegram notifications',
    ],
],

API Endpoints

The package provides REST API endpoints for managing preferences:

GET    /api/notification-preferences          # Get all preferences
PUT    /api/notification-preferences          # Update preferences
POST   /api/notification-preferences/enable   # Enable a channel
POST   /api/notification-preferences/disable  # Disable a channel
GET    /api/notification-preferences/channels # Get available channels
GET    /api/notification-preferences/types    # Get notification types
GET    /api/notification-preferences/history  # Get notification history

Example requests:

// Enable a channel
POST /api/notification-preferences/enable
{
    "notification_type": "order.shipped",
    "channel": "mail"
}

// Bulk update preferences
PUT /api/notification-preferences
{
    "preferences": {
        "order.shipped": {
            "mail": true,
            "sms": false,
            "database": true
        },
        "order.delivered": {
            "mail": true,
            "database": true
        }
    }
}

Notification History

Track notification history for users:

// Get all notification history
$history = $user->getNotificationHistory();

// Get history for specific notification type
$history = $user->getNotificationHistory('order.shipped', 50);

// Via the manager
$history = NotificationManager::getNotificationHistory($user, 'order.shipped', 100);

Configuration Options

Edit config/notification-management.php:

return [
    // Register custom channels
    'channels' => [
        // Your custom channels here
    ],

    // Routes configuration
    'routes' => [
        'enabled' => true,
        'middleware' => ['auth:sanctum'],
        'prefix' => 'api/notification-preferences',
    ],

    // Default settings
    'defaults' => [
        'enabled_channels' => ['mail', 'database'], // Default channels for new users
        'log_notifications' => true,                 // Enable logging
        'log_table' => 'notification_logs',
    ],

    // Define your notification types
    'notification_types' => [
        'order.created' => 'Order created',
        'order.shipped' => 'Order shipped',
        'order.delivered' => 'Order delivered',
        'user.mentioned' => 'You were mentioned',
    ],
];

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Security

If you discover any security related issues, please email carlossouza.work@gmail.com instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.