Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Notifier Laravel Package

symfony/notifier

Symfony Notifier sends notifications through multiple channels like email, SMS, chat apps, and push. It unifies transports and routing so you can dispatch messages to users via one or more providers with a consistent API.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup in Laravel

  1. Install the package via Composer:
    composer require symfony/notifier
    
  2. Configure a transport (e.g., Twilio for SMS, Mailgun for email) in config/services.php:
    'notifier' => [
        'dsn' => 'sms://default:YOUR_TWILIO_AUTH_TOKEN@default?from=+1234567890',
    ],
    
  3. Define a notification class (e.g., app/Notifications/SmsNotification.php):
    use Symfony\Component\Notifier\Notification\Notification;
    use Symfony\Component\Notifier\Notification\SmsNotification;
    
    class SmsNotification extends Notification
    {
        public function __construct(private string $message)
        {
        }
    
        public function asSms(): SmsNotification
        {
            return SmsNotification::create($this->message)
                ->context(['user_id' => 123]);
        }
    }
    
  4. Send the notification in a controller or service:
    use Symfony\Component\Notifier\NotifierInterface;
    use Symfony\Component\Notifier\Bridge\SymfonyMessenger\Transport\SymfonyMessengerTransportFactory;
    
    public function sendNotification(NotifierInterface $notifier)
    {
        $notification = new SmsNotification('Your order is confirmed!');
        $notifier->send($notification);
    }
    

First Use Case: Password Reset SMS

// In a Laravel controller or command
$notifier = app(NotifierInterface::class);
$notification = new SmsNotification("Reset your password: http://example.com/reset/{$token}");
$notifier->send($notification);

Implementation Patterns

1. Channel-Agnostic Notification Design

  • Pattern: Use a base Notification class and extend for channel-specific logic.
    class BaseNotification extends Notification
    {
        public function __construct(private string $title, private string $message)
        {
        }
    
        public function asEmail(): EmailNotification
        {
            return EmailNotification::create($this->title, $this->message)
                ->html($this->renderHtml());
        }
    
        public function asSms(): SmsNotification
        {
            return SmsNotification::create($this->message)
                ->context(['short_code' => 'ORDER']);
        }
    }
    
  • Workflow: Instantiate once, send to multiple channels:
    $notification = new BaseNotification('Order Update', 'Your order is shipping!');
    $notifier->send($notification->asEmail());
    $notifier->send($notification->asSms());
    

2. Dynamic Recipients with Laravel Models

  • Pattern: Attach recipients dynamically using Laravel’s Eloquent relationships.
    class UserNotification extends Notification
    {
        public function __construct(private User $user)
        {
        }
    
        public function asSms(): SmsNotification
        {
            return SmsNotification::create("Hello {$this->user->name}, your balance is {$this->user->balance}.")
                ->to($this->user->phone);
        }
    }
    
  • Usage:
    $user = User::find(1);
    $notifier->send(new UserNotification($user));
    

3. Retry and Fallback Logic

  • Pattern: Use Symfony Messenger for retries and fallback transports.
    // config/services.php
    'notifier' => [
        'transports' => [
            'sms' => 'sms://default:token@default?from=+1234',
            'fallback_sms' => 'sms://backup:token@backup?from=+1234',
        ],
        'fallback_transports' => ['fallback_sms'],
    ],
    
  • Workflow: Configure retries in config/messenger.php:
    'transports' => [
        'async' => [
            'dsn' => 'sync://',
            'options' => [
                'retries' => 3,
                'delay' => 1000,
            ],
        ],
    ],
    

4. Webhook Handling (Slack/Discord)

  • Pattern: Create a WebhookNotification for interactive messages.
    use Symfony\Component\Notifier\Notification\WebhookNotification;
    
    class SlackAlert extends Notification
    {
        public function asSlack(): WebhookNotification
        {
            return WebhookNotification::create('Deployment Failed', 'Check logs at http://example.com/logs')
                ->block(new SlackSectionBlock('Error Details', 'Server: prod, Time: ' . now()))
                ->action(new SlackButtonBlockElement('View Logs', 'http://example.com/logs'));
        }
    }
    
  • Usage:
    $notifier->send(new SlackAlert());
    

5. Integration with Laravel Events

  • Pattern: Dispatch notifications via Laravel Events.
    // Event
    class OrderShipped implements ShouldBroadcast
    {
        public function broadcastOn(): array
        {
            return [new NotificationChannel()];
        }
    
        public function toNotifier(array $notifiers, Notification $notification)
        {
            return $notification->asSms();
        }
    }
    
  • Service Provider:
    public function boot()
    {
        Notification::route(
            OrderShipped::class,
            new NotificationRecipient('sms', '+1234567890')
        );
    }
    

Gotchas and Tips

1. Transport Configuration Pitfalls

  • Issue: Incorrect DSN format causes silent failures.
    • Fix: Use the DSN helper to validate:
      $dsn = Dsn::fromString('sms://default:token@default?from=+1234');
      
    • Laravel Tip: Store DSNs in .env and validate in AppServiceProvider:
      public function boot()
      {
          $this->validateDsns();
      }
      
      protected function validateDsns()
      {
          $dsn = config('services.notifier.dsn');
          if (!$dsn || !Dsn::fromString($dsn)->isValid()) {
              throw new \RuntimeException('Invalid Notifier DSN');
          }
      }
      

2. Recipient Formatting

  • Issue: SMS/Email recipients must match the transport’s expected format.
    • Fix: Use NotificationRecipient for type safety:
      $recipient = new NotificationRecipient('sms', '+1234567890'); // Validates E.164 format
      $notifier->send($notification->to($recipient));
      
    • Laravel Tip: Add a recipient() method to notifications:
      public function recipient(): NotificationRecipient
      {
          return new NotificationRecipient('sms', $this->user->phone);
      }
      

3. Debugging Failed Notifications

  • Issue: Notifications disappear without error logs.
    • Fix: Enable Symfony Messenger’s debug mode:
      // config/messenger.php
      'defaults' => [
          'transport' => 'async',
          'dsn' => env('MESSENGER_TRANSPORT_DSN', 'sync://'),
          'options' => [
              'logger' => true, // Logs all messages
          ],
      ],
      
    • Laravel Tip: Use tap() to inspect notifications:
      $notifier->send(
          (new SmsNotification('Test'))
              ->to('+1234567890')
              ->tap(function ($notification) {
                  \Log::debug('Sending:', [
                      'recipient' => $notification->getRecipients()[0],
                      'content' => $notification->getSubject(),
                  ]);
              })
      );
      

4. Channel-Specific Quirks

Channel Gotcha Solution
Slack Blocks exceed 3000 chars Use SlackSectionBlock::setText() with truncation.
Twilio SMS Whitespace in from number Trim and validate: $from = trim($from).
Email HTML emails in plaintext fallback Use EmailNotification::html() + text().
Telegram Markdown parsing errors Escape special chars: $message = str_replace(['*', '_'], ['\*', '\_'], $message).
Discord Embed limits (256 chars title) Split messages or use DiscordEmbedNotification.

5. Performance Optimization

  • Issue: High latency for bulk notifications.
    • Fix: Batch notifications with Symfony Messenger:
      // config/messenger.php
      'routing' => [
          Notification::class => 'async',
      ],
      
    • Laravel Tip:
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope