This package provides notification management functionality with support for registering and managing different recipient types and notification channels.
- Singleton
NotificationManagerservice for managing recipient types and notification channels - Facade for easy access
- Register custom recipient types and channels with callback pattern
- Query registered recipient types and channels
The package is auto-registered via Laravel's service provider discovery.
You can register notification channels in your service provider's boot() method:
use Juzaweb\Modules\Notification\Facades\Notification;
use Juzaweb\Modules\Notification\Channels\EmailChannel;
// Register using a class
Notification::registerChannel('email', fn() => new EmailChannel());
// Or register using anonymous class
Notification::registerChannel('sms', function () {
return new class implements NotificationChannelInterface {
public function getLabel(): string {
return 'SMS';
}
public function getDescription(): ?string {
return 'Send notifications via SMS';
}
public function toArray(): array {
return [
'label' => $this->getLabel(),
'description' => $this->getDescription(),
];
}
};
});You can register recipient types in your service provider's boot() method:
use Juzaweb\Modules\Notification\Facades\Notification;
// Register recipient types with callback pattern
Notification::registerRecipientType('all_users', function () {
return new class implements RecipientTypeInterface {
public function getLabel(): string {
return 'All Users';
}
public function getDescription(): ?string {
return 'Send to all registered users';
}
public function toArray(): array {
return [
'label' => $this->getLabel(),
'description' => $this->getDescription(),
];
}
};
});
Notification::registerRecipientType('premium_users', function () {
return new class implements RecipientTypeInterface {
public function getLabel(): string {
return 'Premium Users';
}
public function getDescription(): ?string {
return 'Send to users with premium subscription';
}
public function toArray(): array {
return [
'label' => $this->getLabel(),
'description' => $this->getDescription(),
];
}
};
});You can create your own custom recipient type classes by implementing RecipientTypeInterface:
use Juzaweb\Modules\Notification\Contracts\RecipientTypeInterface;
class PremiumUsersRecipientType implements RecipientTypeInterface
{
public function getLabel(): string
{
return __('Premium Users');
}
public function getDescription(): ?string
{
return __('Send to users with active premium subscription');
}
public function toArray(): array
{
return [
'label' => $this->getLabel(),
'description' => $this->getDescription(),
];
}
// You can add custom methods
public function getRecipients(): array
{
// Custom logic to get recipients
return User::where('is_premium', true)->get();
}
}
// Register the custom type
Notification::registerRecipientType('premium_users', fn() => new PremiumUsersRecipientType());Create notification channels by implementing NotificationChannelInterface:
use Juzaweb\Modules\Notification\Contracts\NotificationChannelInterface;
class PushNotificationChannel implements NotificationChannelInterface
{
public function getLabel(): string
{
return __('Push Notification');
}
public function getDescription(): ?string
{
return __('Send push notifications to mobile devices');
}
public function toArray(): array
{
return [
'label' => $this->getLabel(),
'description' => $this->getDescription(),
];
}
}
// Register the custom channel
Notification::registerChannel('push', fn() => new PushNotificationChannel());use Juzaweb\Modules\Notification\Facades\Notification;
// Get all registered recipient types (as objects)
$recipientTypes = Notification::getRecipientTypes();
/*
Returns array of RecipientTypeInterface objects:
[
'all_users' => RecipientType object,
'premium_users' => PremiumUsersRecipientType object,
// ...
]
*/
// Get all registered recipient types as arrays
$recipientTypesArray = Notification::getRecipientTypesArray();
/*
Returns:
[
'all_users' => [
'label' => 'All Users',
'description' => 'Send to all registered users'
],
'premium_users' => [
'label' => 'Premium Users',
'description' => 'Send to users with premium subscription'
],
// ...
]
*/
// Get a specific recipient type (as object)
$type = Notification::getRecipientType('all_users');
// Returns RecipientTypeInterface object or null
// Access properties
if ($type) {
echo $type->getLabel(); // "All Users"
echo $type->getDescription(); // "Send to all registered users"
}use Juzaweb\Modules\Notification\Facades\Notification;
// Get all registered channels (as objects)
$channels = Notification::getChannels();
// Get all registered channels as arrays
$channelsArray = Notification::getChannelsArray();
/*
Returns:
[
'email' => [
'label' => 'Email',
'description' => 'Send notifications via email'
],
'sms' => [
'label' => 'SMS',
'description' => 'Send notifications via SMS'
],
// ...
]
*/
// Check if a channel exists
if (Notification::hasChannel('email')) {
// Channel exists
}In your controller:
use Juzaweb\Modules\Notification\Facades\Notification;
public function create()
{
// Get as array for easier use in views
$recipientTypes = Notification::getRecipientTypesArray();
$channels = Notification::getChannelsArray();
return view('notification::create', compact('recipientTypes', 'channels'));
}In your Blade view:
<select name="recipient_type" class="form-control">
@foreach($recipientTypes as $key => $type)
<option value="{{ $key }}">
{{ $type['label'] }}
@if(!empty($type['description']))
- {{ $type['description'] }}
@endif
</option>
@endforeach
</select>
<select name="channels[]" class="form-control" multiple>
@foreach($channels as $key => $channel)
<option value="{{ $key }}">
{{ $channel['label'] }}
@if(!empty($channel['description']))
- {{ $channel['description'] }}
@endif
</option>
@endforeach
</select>Mark channels as subscriptable to allow users to subscribe/unsubscribe:
use Juzaweb\Modules\Notification\Facades\Notification;
// Mark a channel as subscriptable
Notification::subscriptable('email', [
'can_unsubscribe' => true,
'default_enabled' => true,
]);
Notification::subscriptable('sms', [
'can_unsubscribe' => true,
'default_enabled' => false,
]);
// Get all subscriptable channels
$subscriptableChannels = Notification::getSubscriptableChannels();
// Returns: ['email', 'sms']
// Get subscriptable data for a specific channel
$emailData = Notification::getSubscriptableData('email');
/*
Returns:
[
'can_unsubscribe' => true,
'default_enabled' => true,
]
*/Use the SendNotificationJob to send notifications to multiple recipients:
use Juzaweb\Modules\Notification\Jobs\SendNotificationJob;
use Juzaweb\Modules\Notification\Models\SentNotification;
// Create a notification
$notification = SentNotification::create([
'title' => 'System Maintenance',
'message' => 'The system will be under maintenance tomorrow.',
'recipient_type' => 'all_users',
'via' => ['email', 'database'],
]);
// Dispatch job to send notifications
SendNotificationJob::dispatch($notification);
// Or with custom chunk size (default is 100)
SendNotificationJob::dispatch($notification, 50);The job will:
- Get recipients from the registered recipient type
- Process recipients in chunks to avoid memory issues
- Send notifications via specified channels
- Update the
sent_attimestamp when complete
From the admin panel, you can select multiple notifications and perform bulk actions:
- Delete: Remove selected notifications
- Send: Queue selected notifications for sending
// In your controller
public function bulk(SentNotificationActionsRequest $request)
{
$action = $request->input('action'); // 'delete' or 'sent'
$ids = $request->input('ids', []);
$models = SentNotification::whereIn('id', $ids)->get();
foreach ($models as $model) {
if ($action === 'delete') {
$model->delete();
}
if ($action === 'sent') {
SendNotificationJob::dispatch($model);
}
}
}Register a new recipient type.
Parameters:
$key- The unique key for the recipient type$callback- Callback that returns aRecipientTypeInterfaceinstance
Returns: self for method chaining
Example:
Notification::registerRecipientType('all_users', fn() => new AllUsersRecipientType());Register a new notification channel.
Parameters:
$key- The unique key for the channel$callback- Callback that returns aNotificationChannelInterfaceinstance
Returns: self for method chaining
Example:
Notification::registerChannel('email', fn() => new EmailChannel());Get all registered recipient types as objects.
Returns: Array of RecipientTypeInterface objects indexed by key
Get all registered recipient types as arrays (useful for views).
Returns: Array of arrays with label and description for each type
Get a specific recipient type by key.
Parameters:
$key- The recipient type key
Returns: RecipientTypeInterface object or null if not found
Check if a recipient type is registered.
Parameters:
$key- The recipient type key
Returns: true if exists, false otherwise
Remove a recipient type.
Parameters:
$key- The recipient type key to remove
Returns: self for method chaining
Get all registered channels as objects.
Returns: Array of NotificationChannelInterface objects indexed by key
Get all registered channels as arrays (useful for views).
Returns: Array of arrays with label and description for each channel
Check if a channel is registered.
Parameters:
$key- The channel key
Returns: true if exists, false otherwise
Remove a channel.
Parameters:
$key- The channel key to remove
Returns: self for method chaining
Mark a channel as subscriptable, allowing users to subscribe or unsubscribe.
Parameters:
$channel- The channel key$data- Optional configuration data (e.g.,['can_unsubscribe' => true])
Example:
Notification::subscriptable('email', [
'can_unsubscribe' => true,
'default_enabled' => true,
]);Get all channels marked as subscriptable.
Returns: Array of channel keys that are subscriptable
Example:
$channels = Notification::getSubscriptableChannels();
// Returns: ['email', 'sms', 'push']Get the subscriptable configuration data for a specific channel.
Parameters:
$channel- The channel key
Returns: Array of configuration data for the channel, or empty array if not found
Example:
$data = Notification::getSubscriptableData('email');
/*
Returns:
[
'can_unsubscribe' => true,
'default_enabled' => true,
]
*/Interface that all recipient type classes must implement.
Get the display label for the recipient type.
Get the description for the recipient type (optional).
Convert the recipient type to an array representation.
Returns: Array with label and description keys
Get the Eloquent query builder for fetching recipients.
Returns: Eloquent Builder instance that can be used to fetch recipients
Example:
public function getRecipients(): \Illuminate\Database\Eloquent\Builder
{
return User::where('is_premium', true);
}Interface that all notification channel classes must implement.
Get the display label for the notification channel.
Get the description for the notification channel (optional).
Convert the notification channel to an array representation.
Returns: Array with label and description keys
use Juzaweb\Modules\Notification\Contracts\RecipientTypeInterface;
use App\Models\User;
class ActiveUsersRecipientType implements RecipientTypeInterface
{
public function getLabel(): string
{
return __('Active Users');
}
public function getDescription(): ?string
{
return __('Users who have logged in within the last 30 days');
}
public function getRecipients(): \Illuminate\Database\Eloquent\Builder
{
return User::where('last_login_at', '>=', now()->subDays(30))
->whereNotNull('email');
}
public function toArray(): array
{
return [
'label' => $this->getLabel(),
'description' => $this->getDescription(),
];
}
}
// Register it
Notification::registerRecipientType('active_users', fn() => new ActiveUsersRecipientType());use Juzaweb\Modules\Notification\Jobs\SendNotificationJob;
use Juzaweb\Modules\Notification\Models\SentNotification;
use Juzaweb\Modules\Notification\Exceptions\RecipientTypeNotFoundException;
try {
$notification = SentNotification::create([
'title' => 'Welcome!',
'message' => 'Thank you for joining us.',
'recipient_type' => 'new_users',
'via' => ['email', 'database'],
]);
SendNotificationJob::dispatch($notification);
} catch (RecipientTypeNotFoundException $e) {
Log::error('Recipient type not found: ' . $e->getMessage());
}// Unregister a recipient type
Notification::unregisterRecipientType('old_type');
// Unregister a channel
Notification::unregisterChannel('deprecated_channel');
// Check before unregistering
if (Notification::hasRecipientType('temp_type')) {
Notification::unregisterRecipientType('temp_type');
}Same as the main application license.