offload-project/laravel-notification-preferences 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

offload-project/laravel-notification-preferences

最新稳定版本:v1.1.0

Composer 安装命令:

composer require offload-project/laravel-notification-preferences

包简介

Manage and display user notification preferences in Laravel

README 文档

README

Latest Version on Packagist GitHub Tests Action Status Total Downloads

Laravel Notification Preferences

A Laravel package for managing user notification preferences with support for multiple channels, notification groups, and automatic channel filtering — perfect for building notification settings UIs.

Features

  • Automatic Filtering — All notifications respect user preferences without code changes
  • Multiple Channels — Support for mail, database, broadcast, SMS, or custom channels
  • Notification Grouping — Organize notifications into logical groups (system, marketing, etc.)
  • Forced Channels — Critical notifications that users cannot disable
  • Bulk Operations — Disable all emails, mute a group, or toggle notification types
  • Structured Output — UI-ready table structure for building preference pages
  • Opt-in/Opt-out Defaults — Configure default behavior at global, group, or notification level
  • Event Dispatching — Listen for preference changes for audit logging or sync
  • Input Validation — Prevents setting preferences for unregistered notifications/channels

Requirements

  • PHP 8.3+
  • Laravel 11+

Installation

composer require offload-project/laravel-notification-preferences

Publish the config and migrations:

php artisan vendor:publish --tag=notification-preferences-config
php artisan vendor:publish --tag=notification-preferences-migrations
php artisan migrate

Quick Start

1. Add the trait to your User model:

use OffloadProject\NotificationPreferences\Concerns\HasNotificationPreferences;

class User extends Authenticatable
{
    use HasNotificationPreferences;
}

2. Register your notifications in config/notification-preferences.php:

return [
    'channels' => [
        'mail' => ['label' => 'Email', 'enabled' => true],
        'database' => ['label' => 'In-App', 'enabled' => true],
    ],

    'groups' => [
        'system' => [
            'label' => 'System Notifications',
            'description' => 'Important system updates',
            'default_preference' => 'opt_in',
            'order' => 1,
        ],
    ],

    'notifications' => [
        \App\Notifications\OrderShipped::class => [
            'group' => 'system',
            'label' => 'Order Shipped',
            'description' => 'When your order ships',
            'order' => 1,
        ],
    ],
];

3. Send notifications normally — preferences are applied automatically:

$user->notify(new OrderShipped($order));

Managing Preferences

// Set a preference
$user->setNotificationPreference(OrderShipped::class, 'mail', false);

// Check a preference
$enabled = $user->getNotificationPreference(OrderShipped::class, 'mail');

// Get all preferences
$preferences = $user->getNotificationPreferences();

// Get structured table for UI
$table = $user->getNotificationPreferencesTable();

Bulk Operations

Convenient methods for "disable all emails" or "mute marketing" features:

// Disable all emails
$user->setChannelPreferences('mail', false);

// Mute all marketing notifications for email
$user->setGroupPreferences('marketing', 'mail', false);

// Disable all channels for a notification type
$user->setNotificationChannelPreferences(OrderShipped::class, false);

// Reset all preferences to defaults
$user->resetNotificationPreferences();

All bulk methods return the count of updated preferences and automatically skip forced channels.

Explicit Control with Trait

For granular control, use the ChecksNotificationPreferences trait in your notification:

use OffloadProject\NotificationPreferences\Concerns\ChecksNotificationPreferences;

class OrderShipped extends Notification
{
    use ChecksNotificationPreferences;

    public function via($notifiable)
    {
        return $this->allowedChannels($notifiable, ['mail', 'database', 'broadcast']);
    }
}

Forced Channels

Prevent users from disabling critical notifications:

'notifications' => [
    SecurityAlert::class => [
        'group' => 'security',
        'label' => 'Security Alerts',
        'force_channels' => ['mail', 'database'],
    ],
],

Per-Channel Defaults

Set specific channels enabled by default:

'notifications' => [
    OrderShipped::class => [
        'group' => 'system',
        'label' => 'Order Shipped',
        'default_channels' => ['mail', 'database'], // Only these enabled by default
    ],
],

Events

The package dispatches events when preferences change:

use OffloadProject\NotificationPreferences\Events\NotificationPreferenceChanged;

Event::listen(NotificationPreferenceChanged::class, function ($event) {
    // $event->preference - The NotificationPreference model
    // $event->user - The user who changed the preference
    // $event->wasCreated - Whether this was a new preference or update
});

Using the Facade

For quick access without dependency injection:

use OffloadProject\NotificationPreferences\Facades\NotificationPreferences;

// Check if a channel is enabled
NotificationPreferences::isChannelEnabled($user, OrderShipped::class, 'mail');

// Set a preference
NotificationPreferences::setPreference($user, OrderShipped::class, 'mail', false);

// Get structured table for UI
NotificationPreferences::getPreferencesTable($user);

// Discover registered configuration
NotificationPreferences::getRegisteredChannels();    // ['mail', 'database']
NotificationPreferences::getRegisteredGroups();      // ['system', 'marketing']
NotificationPreferences::getRegisteredNotifications(); // [OrderShipped::class, ...]

Using the Interface

For dependency injection and testing, use the interface:

use OffloadProject\NotificationPreferences\Contracts\NotificationPreferenceManagerInterface;

class NotificationPreferenceController
{
    public function __construct(
        private NotificationPreferenceManagerInterface $manager
    ) {}

    public function update(Request $request)
    {
        $this->manager->setPreference(
            $request->user(),
            $request->notification_type,
            $request->channel,
            $request->enabled
        );
    }
}

Table Structure Output

The getNotificationPreferencesTable() method returns UI-ready data:

[
    [
        'group' => 'system',
        'label' => 'System Notifications',
        'description' => 'Important system updates',
        'notifications' => [
            [
                'type' => 'App\Notifications\OrderShipped',
                'label' => 'Order Shipped',
                'description' => 'When your order ships',
                'channels' => [
                    'mail' => ['enabled' => true, 'forced' => false],
                    'database' => ['enabled' => true, 'forced' => false],
                ],
            ],
        ],
    ],
]

Inertia.js Integration

Share preferences via middleware:

// app/Http/Middleware/HandleInertiaRequests.php
public function share(Request $request): array
{
    return [
        ...parent::share($request),
        'notificationPreferences' => fn () => $request->user()?->getNotificationPreferencesTable(),
    ];
}

Cache Management

Preferences are cached for performance (default: 24 hours). Configure the TTL in your config:

// config/notification-preferences.php
'cache_ttl' => 1440, // minutes (default: 24 hours)

Clear caches when needed:

use OffloadProject\NotificationPreferences\Contracts\NotificationPreferenceManagerInterface;

$manager = app(NotificationPreferenceManagerInterface::class);

// Clear all cached preferences for a user
$manager->clearUserCache($userId);

// Clear the memoized config cache (useful after runtime config changes)
$manager->clearConfigCache();

Exception Handling

The package validates all inputs and throws specific exceptions with helpful messages:

use OffloadProject\NotificationPreferences\Exceptions\InvalidNotificationTypeException;
use OffloadProject\NotificationPreferences\Exceptions\InvalidChannelException;
use OffloadProject\NotificationPreferences\Exceptions\InvalidGroupException;

try {
    $user->setNotificationPreference('UnregisteredNotification', 'mail', false);
} catch (InvalidNotificationTypeException $e) {
    // "Notification type 'UnregisteredNotification' is not registered...
    //  Add it to the 'notifications' array in 'config/notification-preferences.php'."
}

try {
    $user->setNotificationPreference(OrderShipped::class, 'sms', false);
} catch (InvalidChannelException $e) {
    // "Channel 'sms' is not registered... Available channels: mail, database."
}

try {
    $user->setGroupPreferences('nonexistent', 'mail', false);
} catch (InvalidGroupException $e) {
    // "Group 'nonexistent' is not registered... Available groups: system, marketing."
}

Uninstalling

php artisan notification-preferences:uninstall --force
composer remove offload-project/laravel-notification-preferences
rm config/notification-preferences.php

Configuration Reference

Global Options

Option Type Description
default_preference string opt_in or opt_out for all notifications
cache_ttl int Cache duration in minutes (default: 1440 = 24h)
table_name string Database table name (default: notification_preferences)
user_model string User model class (default: App\Models\User)

Channels

Option Type Description
label string Display name for UI
enabled bool Whether channel is available (default: true)

Groups

Option Type Description
label string Display name for UI
description string Optional description for UI
default_preference string opt_in or opt_out (overrides global)
order int Sort order in UI

Notifications

Option Type Description
group string Group key this notification belongs to
label string Display name for UI
description string Optional description for UI
default_preference string opt_in or opt_out (overrides group)
default_channels array Specific channels enabled by default
force_channels array Channels that cannot be disabled
order int Sort order within group

Testing

./vendor/bin/pest

License

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

统计信息

  • 总下载量: 104
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 4
  • 点击次数: 0
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 4
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2025-12-16