Notifications and notification preference system for Audentio Laravel platforms. Provides a database-backed notification preference system with per-channel defaults, per-tenant overrides, per-user overrides, a GraphQL API, and optional push notification support.
- PHP 8.1+
- Laravel 12
audentio/laravel-base
composer require audentio/laravel-notificationsPublish and run the migrations:
php artisan vendor:publish --tag=audentio-notifications-config
php artisan migratePublish the model stubs:
php artisan vendor:publish --tag=audentio-notifications-modelsThe published stubs in app/Models/ need to be wired up to your application. At minimum:
NotificationPreference — extend getDefaultUserNotificationPreferenceValue() if needed. The getName() method must return a human-readable label (typically from a translation key).
NotificationPreferenceGroup — same, getName() must be implemented.
UserNotificationPreference — no changes needed beyond the stub.
use Audentio\LaravelNotifications\Models\Interfaces\NotifiableUserInterface;
use Audentio\LaravelNotifications\Models\Traits\NotifiableUserTrait;
class User extends Model implements NotifiableUserInterface
{
use NotifiableUserTrait;
public function isEmailVerified(): bool
{
return $this->email_verified_at !== null;
}
}Extend AbstractNotification and implement getNotificationPreferenceId():
use Audentio\LaravelNotifications\Notifications\AbstractNotification;
class NewMessageNotification extends AbstractNotification
{
public function getNotificationPreferenceId(): string
{
return 'newMessage';
}
public function toMail($notifiable): MailMessage
{
return (new MailMessage)->subject('New message');
}
}Run your NotificationPreferencesAndGroupsTableSeeder after adding handlers. The seeder auto-discovers handlers and creates NotificationPreference records.
User preferences follow a 3-level fallback (highest priority first):
| Level | Source | Stored in |
|---|---|---|
| 3 | User override | user_notification_preferences.disabled_channels |
| 2 | Tenant override | App-provided via getNotificationPreferenceTenantDefaults() |
| 1 | Global default | notification_preferences.default_disabled_channels |
When no record exists at a level, the next level is used. An empty disabled_channels array means all channels are enabled.
Set default_disabled_channels when seeding a preference:
'streamGoLive' => [
'available_channels' => ['notification', 'mail'],
'default_disabled_channels' => ['mail'], // mail off by default for all users
],Override getNotificationPreferenceTenantDefaults() on your User model to load tenant-specific defaults. This is called once per getUserNotificationPreferenceValues() call — load all tenant preferences in a single query:
public function getNotificationPreferenceTenantDefaults(): Collection
{
$tenant = $this->getCurrentTenant();
if (!$tenant) {
return collect();
}
return TenantNotificationPreference::where('tenant_id', $tenant->id)->get();
}If you manage migrations manually:
// In a service provider
LaravelNotifications::skipMigrations();Enable push support in config/audentioNotifications.php:
'push_enabled' => true,
'push_handler_classes' => [
'expo' => \Audentio\LaravelNotifications\PushHandlers\ExpoPushHandler::class,
'fcm' => \Audentio\LaravelNotifications\PushHandlers\FirebasePushHandler::class,
],Run the additional push migrations:
php artisan migratePush subscriptions are managed via the routeNotificationForPush() method on your User model (provided by NotifiableUserTrait — override if needed).
The package auto-registers a GraphQL schema when audentio/laravel-graphql is present. Exposed types, queries, and mutations include:
- Queries:
notifications,notificationPreferenceGroups - Mutations:
updateViewerNotificationPreferenceValue,dismissNotification,markReadNotification,markUnreadNotification,markReadAllNotifications,dismissAllNotifications - Types:
NotificationPreference,NotificationPreferenceGroup,UserNotificationPreferenceValue,NotificationChannelEnum
Override individual types via graphQL_schema_overrides in the config.
To disable GraphQL registration:
LaravelNotifications::skipGraphQLSchema();composer testMIT