Contents
Most notification systems start simple. Send a confirmation email when an order is placed. Done. Then the product team asks for SMS. Then someone wants a Slack alert when a high-value order comes in. Before long, you've got three separate integrations — each with their own configuration, error handling, and mental overhead.
Laravel's notification system was built for exactly this situation. One notification class, multiple delivery channels, all coordinated from the framework.
How Laravel Notifications Work
A Laravel notification is a class that answers one question: given a channel, how should this message be formatted? You define the channels on a per-notification basis, and the framework handles routing.
class OrderPlaced extends Notification
{
public function __construct(public Order $order) {}
public function via(object $notifiable): array
{
return ['mail', 'vonage', 'slack'];
}
}
That via() method is the whole routing decision. The notification goes to every channel listed. If you want to make it conditional — SMS only for orders over $500, for example — you just put that logic in via(). Clean, obvious, no separate orchestration service needed.
The Mail Channel
Email is the default. Laravel's toMail() method returns a MailMessage object that builds a clean transactional email using the framework's built-in Markdown templates.
public function toMail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject("Your order #{$this->order->id} is confirmed")
->line("Thanks for your order. We'll send tracking once it ships.")
->action('View Order', url("/orders/{$this->order->id}"))
->line("Questions? Reply to this email.");
}
The Markdown email template is responsive, looks professional, and matches across clients. You can customize the template to match your brand — the vendor:publish command exports it so you can edit it directly.
SMS via Vonage (or Twilio)
For SMS, Laravel ships with first-party support for Vonage. Add your credentials to .env and implement toVonage():
public function toVonage(object $notifiable): VonageMessage
{
return (new VonageMessage)
->content("Order #{$this->order->id} confirmed. We'll text you when it ships.");
}
Prefer Twilio? There's a community package that adds a Twilio channel with identical ergonomics. The notification class stays the same shape — you're just swapping the channel driver.
Slack Notifications
Slack is where a lot of teams want operational alerts — new signups, large orders, payment failures. The Slack notification channel lets you send structured messages with blocks, attachments, and action buttons.
public function toSlack(object $notifiable): SlackMessage
{
return (new SlackMessage)
->text("New order placed")
->attachment(function ($attachment) {
$attachment->title("Order #{$this->order->id}")
->fields([
'Customer' => $this->order->customer->name,
'Total' => '$' . number_format($this->order->total, 2),
]);
});
}
Your team gets a Slack message with real data, formatted cleanly, without any custom Slack API code.
The Database Channel and Notification Center
The database channel stores notifications in a notifications table. This is how you build an in-app notification center — the bell icon with a badge count that users have come to expect.
public function toArray(object $notifiable): array
{
return [
'order_id' => $this->order->id,
'message' => "Your order has been confirmed.",
];
}
Laravel ships with $user->notifications, $user->unreadNotifications, and markAsRead() on every model that uses the Notifiable trait. The data layer for a notification center is already there.
Sending Notifications
Sending is one line:
$user->notify(new OrderPlaced($order));
Or dispatch it on a queue so it doesn't block the response:
$user->notify((new OrderPlaced($order))->delay(now()->addSeconds(5)));
Notifications implement ShouldQueue the same way jobs do. High-volume apps should always queue notifications — especially if you're hitting multiple channels at once.
Why This Beats a Separate Orchestration Layer
The alternative is an external service — Customer.io, Iterable, Klaviyo — where you define logic in a third-party dashboard, map event triggers, and maintain a parallel system outside your codebase.
For simple transactional notifications, that's overkill. The logic lives in your Laravel app, it's version-controlled, it's testable, and you're not paying per notification to a third party. When requirements change, you update a PHP class — not a flow diagram in a vendor dashboard.
For complex marketing automation with conditional branching and audience segmentation, a dedicated platform makes sense. But for "send an email, maybe an SMS, ping Slack if it's big" — Laravel's notification system handles it without leaving the framework.
If your app needs to reach customers reliably across channels without bolting on a separate service, let's talk about how to build it cleanly.