Sending notifications
A BaseNotify subclass is an ordinary Laravel notification: send it with $notifiable->notify() or Notification::send(). What the package adds happens inside it — via() decides the channels, toMail() / toArray() pick the template.
Two sending patterns cover most cases.
Per role, from an event listener
Section titled “Per role, from an event listener”The event fires; the listener asks your recipient resolver who should get it, grouped by role, and sends one notification per role so each role gets its own template and channels:
use App\Events\OrderOrdered;use App\Notifications\OrderOrderedNotify;use Fomvasss\NotifyTemplates\Contracts\NotifyRoleResolverInterface;use Fomvasss\NotifyTemplates\Facades\NotifyTemplates;use Illuminate\Support\Facades\Notification;
class SendOrderOrderedNotifications{ public function __construct(protected NotifyRoleResolverInterface $resolver) {}
public function handle(OrderOrdered $event): void { $order = $event->order->fresh();
foreach ($this->resolver->resolveUsersForNotify('OrderOrdered', $order) as $roleKey => $users) { Notification::send( $users, (new OrderOrderedNotify($order, $roleKey)) ->delay(NotifyTemplates::resolveDelay('OrderOrdered', $roleKey)), ); } }}sequenceDiagram
participant App as App code
participant Listener
participant Resolver as NotifyRoleResolverInterface
participant Laravel as Notification::send()
participant Notify as OrderOrderedNotify
App->>Listener: event(new OrderOrdered($order))
Listener->>Resolver: resolveUsersForNotify('OrderOrdered', $order)
Resolver-->>Listener: ['role_key' => users]
loop each role_key
Listener->>Laravel: send($users, new OrderOrderedNotify($order, $roleKey))
Laravel->>Notify: via($user) — opt-outs, subscription, routes
Laravel->>Notify: toMail($user) / toTelegram($user) / ...
Notify->>Notify: resolveTemplate() — DB row or typeDefinition defaults
end
resolveDelay() returns seconds from the subscription’s options.delay (minutes), 0 without a subscription. delay() comes from Queueable and works only for queued notifications.
Directly, to one notifiable
Section titled “Directly, to one notifiable”For notifications triggered by the user’s own action — a login code, a password reset — send to the user directly with the role whose subscription and template apply:
$user->notify(new UserOtpNotify(roleKey: 'client', code: $code));Mark such types 'user_configurable' => false when they must always arrive: they then go out through default_channels even without an active subscription. See User preferences.
Narrowing channels at the call site
Section titled “Narrowing channels at the call site”only() and except() are applied last in via():
// only the mail out of the resolved channels$user->notify((new UserOtpNotify(roleKey: 'client', code: $code))->only(['mail']));
// all resolved channels except sms$user->notify((new OrderOrderedNotify($order, 'client'))->except(['sms']));To force channels regardless of subscriptions, bypass via() with Laravel’s own sendNow():
Notification::sendNow($user, new UserOtpNotify(roleKey: 'client', code: $code), ['mail']);On-demand recipients
Section titled “On-demand recipients”Send to an address without a model with Notification::route():
Notification::route('mail', 'guest@example.com') ->notify(new OrderOrderedNotify($order, 'guest'));mail is kept when the notifiable has a mail route — routeNotificationFor('mail'), which covers on-demand recipients, routeNotificationForMail() and the email attribute; a notifiable without routeNotificationFor() falls back to ->email. Before 0.12.2 only ->email was checked, so on-demand mail and routeNotificationForMail() were silently dropped. For an on-demand recipient there are no user preferences: isNotifyEnabled() is always true and no per-user channel preference applies; the role subscription still does. See Custom channels for the rest of mapChannel().
What each channel sends
Section titled “What each channel sends”| Channel | Method | Content |
|---|---|---|
mail | toMail() | Template slot mail: subject and body through prepareText() |
database, broadcast | toArray() | ['message' => strip_tags(...)] of the messenger body |
| custom (Telegram, SMS, …) | your to{Channel}() | Usually getMessengerBody() — slot messenger, falling back to mail |
Token substitution is your prepareText() — see Templates.