symfony/notifier
Symfony Notifier sends notifications through multiple channels like email, SMS, chat, and push. It unifies message creation, routing, and transport handling, making it easy to notify users via one or several providers with a consistent API.
Install the package:
composer require symfony/notifier
For Laravel-specific integration, use spatie/laravel-notifier (a wrapper) or manually configure Symfony’s Notifier.
Configure transports (e.g., Slack, SMS, Email):
Add to config/services.php or a dedicated notifier.php config file:
'notifier' => [
'transports' => [
'slack' => [
'dsn' => 'slack://token?channel=general',
],
'sms' => [
'dsn' => 'twilio://account_sid:auth_token?from=+1234567890',
],
],
],
First notification (e.g., send a Slack message):
use Symfony\Component\Notifier\Notifier;
use Symfony\Component\Notifier\Message\SlackMessage;
$notifier = new Notifier();
$message = new SlackMessage('Hello from Laravel!');
$notifier->send($message);
Laravel-specific tip: Use Laravel’s service container to bind the Notifier:
$this->app->singleton(Notifier::class, function ($app) {
return new Notifier($app['config']['notifier.transports']);
});
Send the same alert via email, SMS, and Slack in a single line:
use Symfony\Component\Notifier\Message\Email;
use Symfony\Component\Notifier\Message\SmsMessage;
use Symfony\Component\Notifier\Message\SlackMessage;
$notifier = app(Notifier::class);
$notifier->send([
new Email('alert@example.com', 'Critical Alert', 'System down!'),
new SmsMessage('+1234567890', 'System down!'),
new SlackMessage('System down!', ['channel' => '#alerts']),
]);
.env or config:
$dsn = 'slack://' . env('SLACK_TOKEN') . '?channel=' . env('SLACK_CHANNEL');
$transport = new SlackTransport($dsn);
$notifier->addTransport('slack', $transport);
config() to switch transports per environment:
$notifier->addTransport(
'sms',
new TwilioTransport(config('services.twilio.' . env('APP_ENV') . '.sms'))
);
Rich messages:
$message = new SlackMessage('Deploy failed!');
$message->subject('Deployment Alert');
$message->addButton('Retry', 'https://example.com/retry');
$message = new TelegramMessage('*Critical* alert!');
$email = new Email('user@example.com', 'Invoice', 'body');
$email->from(new Address('no-reply@example.com', 'Support'));
$email->attachFromPath(storage_path('app/invoice.pdf'));
Recipient groups: Route to multiple recipients at once:
$message = new SlackMessage('Weekly update');
$message->recipient('team-a', 'team-b'); // Multiple channels
use Symfony\Component\Notifier\NotifierInterface;
use Illuminate\Support\Facades\Bus;
Bus::dispatch(function () use ($notifier) {
$notifier->send(new SlackMessage('Async alert!'));
});
$notifier->send(new SlackMessage('Async alert!'), [
'transport' => 'sync', // or 'async'
]);
created, updated):
use Illuminate\Database\Eloquent\Model;
class User extends Model {
protected static function booted() {
static::created(function ($user) {
app(NotifierInterface::class)->send(
new SlackMessage("New user: {$user->name}")
);
});
}
}
event(new OrderShipped($order));
// In EventServiceProvider:
OrderShipped::listen(function ($event) {
$notifier->send(new Email($event->user, 'Order Shipped', 'body'));
});
Extend for proprietary APIs:
use Symfony\Component\Notifier\Transport\TransportInterface;
class CustomTransport implements TransportInterface {
public function __send(MessageInterface $message, array $failedRecipients = []): void {
// Implement custom logic (e.g., HTTP request to your API)
}
public function __supports(MessageInterface $message): bool {
return $message instanceof CustomMessage;
}
}
Register it:
$notifier->addTransport('custom', new CustomTransport());
slack://token?channel=#general).
Dsn::parse():
use Symfony\Component\Notifier\Dsn;
$dsn = Dsn::parse('slack://token');
SmsMessage::setRecipient() with E.164 format.Bus::dispatch() or dispatchSync() for critical notifications.failed_jobs table (Laravel) or Symfony’s Notifier logs.
$notifier->send($message, ['transport' => 'slack', 'logger' => true]);
$transport->setLogger(new \Monolog\Logger('notifier'));
php artisan config:clear
env() helper for dynamic DSNs:
$dsn = 'slack://' . env('SLACK_WEBHOOK_URL');
config/notifier.php:
'default_transport' => 'slack',
AbstractMessage for domain-specific messages:
class InvoiceMessage extends AbstractMessage {
public function __construct(string $invoiceId, string $amount) {
parent::__construct('invoice_alert');
$this->invoiceId = $invoiceId;
$this->amount = $amount;
}
}
$notifier->addMiddleware(new class implements MiddlewareInterface {
public function handle(MessageInterface $message, callable $next): void {
// Pre-send logic
$next($message);
// Post-send logic
}
});
WebhookTransport for incoming notifications (e.g., Slack events):
$transport = new WebhookTransport('slack', '/slack/webhook');
$notifier->addTransport('slack_webhook', $transport);
$notifier->send([
new SmsMessage('+123', 'Hello'),
new SmsMessage('+124', 'Hello'),
]);
AppServiceProvider:
public function register() {
$this->app->singleton(NotifierInterface::class, function ($app) {
$notifier = new Notifier();
foreach (config('notifier.transports') as $name => $config) {
$notifier->add
How can I help you explore Laravel packages today?