// 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();
// 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();
use OffloadProject\NotificationPreferences\Concerns\ChecksNotificationPreferences;
class OrderShipped extends Notification
{
use ChecksNotificationPreferences;
public function via($notifiable)
{
return $this->allowedChannels($notifiable, ['mail', 'database', 'broadcast']);
}
}
use OffloadProject\NotificationPreferences\Contracts\AuthorizesNotification;
class OrderShipped extends Notification implements AuthorizesNotification
{
public static function notificationAbility(): string
{
return 'view-orders';
}
}
Gate::define('view-orders', function (User $user, ?OrderShipped $notification = null) {
// $notification is null when called from the preferences UI (no instance exists)
if ($notification) {
return $user->can('view', $notification->order);
}
return $user->can('view-orders');
});
'notifications' => [
OrderShipped::class => [
'group' => 'system',
'label' => 'Order Shipped',
'default_channels' => ['mail', 'database'], // Only these enabled by default
],
],
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
});
use OffloadProject\NotificationPreferences\Events\NotificationAuthorizationDenied;
Event::listen(NotificationAuthorizationDenied::class, function ($event) {
// $event->notifiable - The user the notification was being sent to
// $event->notification - The notification instance
// $event->channel - The channel that was blocked
// $event->ability - The Gate ability that failed
});
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, ...]
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
);
}
}
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();
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."
}
use OffloadProject\NotificationPreferences\Concerns\HasUnsubscribeUrl;
class OrderShipped extends Notification
{
use HasUnsubscribeUrl;
public function toMail($notifiable): MailMessage
{
return $this->withUnsubscribeHeaders(
(new MailMessage)
->line('Your order has shipped!')
->action('Unsubscribe', $this->getUnsubscribeUrl($notifiable)),
$notifiable
);
}
}
// From the user model
$url = $user->notificationUnsubscribeUrl(OrderShipped::class);
$url = $user->notificationResubscribeUrl(OrderShipped::class);
// From the facade
use OffloadProject\NotificationPreferences\Facades\NotificationPreferences;
$url = NotificationPreferences::unsubscribeUrl($user, OrderShipped::class);
$url = NotificationPreferences::resubscribeUrl($user, OrderShipped::class);
// For a specific channel (defaults to 'mail')
$url = NotificationPreferences::unsubscribeUrl($user, OrderShipped::class, 'database');
// config/notification-preferences.php
'unsubscribe' => [
// Whether to register unsubscribe routes
'enabled' => true,
// Route prefix for unsubscribe/resubscribe endpoints
'route_prefix' => 'notification-preferences',
// Middleware for the unsubscribe routes
'middleware' => ['web'],
// Signed URL TTL in minutes (null for permanent/non-expiring)
'url_ttl' => null,
// Redirect to this URL after unsubscribing (with status, notification_type, and channel query params)
// Set to null to return a JSON response instead
'redirect_url' => null,
// Enable resubscribe functionality
'resubscribe_enabled' => true,
],
'redirect_url' => '/notification-settings',
// Redirects to: /notification-settings?status=unsubscribed¬ification_type=App\Notifications\OrderShipped&channel=mail