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

Firebase Notifier Laravel Package

symfony/firebase-notifier

Symfony Notifier bridge for Firebase Cloud Messaging. Configure via FIREBASE_DSN and send notifications with platform-specific options using AndroidNotification, IOSNotification, or WebNotification to customize icons, sounds, actions, and more.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup for Laravel

  1. Install Dependencies Add to composer.json:

    "require": {
        "symfony/notifier": "^6.4",
        "symfony/firebase-notifier": "^6.4"
    }
    

    Run composer install.

  2. Configure Firebase DSN Add to .env:

    FIREBASE_DSN=firebase://USERNAME:PASSWORD@default
    

    Replace USERNAME:PASSWORD with your Firebase service account credentials (or legacy FCM credentials).

  3. First Notification Create a notification class (e.g., app/Notifications/FirebasePushNotification.php):

    use Symfony\Component\Notifier\Message\ChatMessage;
    use Symfony\Component\Notifier\Bridge\Firebase\Notification\AndroidNotification;
    use Symfony\Component\Notifier\Bridge\Firebase\Transport;
    
    class FirebasePushNotification
    {
        public function send(string $token, string $title, string $body): void
        {
            $message = new ChatMessage($body);
            $message->options(
                (new AndroidNotification())
                    ->title($title)
                    ->body($body)
                    ->priority('high')
            );
    
            $chatter = new Transport(
                new \Symfony\Component\Notifier\Transport\ChatTransport(
                    'firebase://' . env('FIREBASE_DSN')
                )
            );
            $chatter->send($message, $token);
        }
    }
    
  4. Use in Laravel Inject the class into a controller/service:

    use App\Notifications\FirebasePushNotification;
    
    class NotificationController extends Controller
    {
        public function __invoke(FirebasePushNotification $notifier)
        {
            $notifier->send(
                'device_fcm_token_here',
                'Hello!',
                'This is your notification.'
            );
        }
    }
    

Implementation Patterns

Workflow: Sending Cross-Platform Notifications

  1. Define Platform-Specific Options Use AndroidNotification, IOSNotification, or WebNotification classes to customize payloads:

    $androidOptions = (new AndroidNotification('/topics/news'))
        ->icon('ic_notification')
        ->sound('default')
        ->priority('high')
        ->data(['key' => 'value']);
    
    $iosOptions = (new IOSNotification())
        ->badge(1)
        ->sound('default')
        ->mutableContent(true);
    
  2. Attach Options to Message

    $message = new ChatMessage('Your content here');
    $message->options($androidOptions); // or $iosOptions
    
  3. Send via Transport

    $transport = new Transport(
        new \Symfony\Component\Notifier\Transport\ChatTransport(
            'firebase://' . env('FIREBASE_DSN')
        )
    );
    $transport->send($message, $deviceToken);
    
  4. Batch Sending (Topics) Target multiple devices via Firebase topics:

    $message->options(
        (new AndroidNotification('/topics/promotions'))
            ->priority('high')
    );
    

Integration with Laravel Services

  1. Service Provider Binding Bind the transport in AppServiceProvider:

    public function boot()
    {
        $this->app->singleton('firebase.notifier', function () {
            return new Transport(
                new \Symfony\Component\Notifier\Transport\ChatTransport(
                    'firebase://' . env('FIREBASE_DSN')
                )
            );
        });
    }
    
  2. Queueable Notifications Use Laravel Queues to defer sending:

    use Illuminate\Bus\Queueable;
    use Illuminate\Contracts\Queue\ShouldQueue;
    
    class FirebaseNotification implements ShouldQueue
    {
        use Queueable;
    
        public function handle()
        {
            $notifier = app('firebase.notifier');
            $notifier->send($this->message, $this->token);
        }
    }
    
  3. Event-Driven Notifications Trigger notifications from Laravel events:

    use Illuminate\Queue\Events\JobProcessed;
    
    Event::listen(JobProcessed::class, function ($event) {
        $notifier = app('firebase.notifier');
        $notifier->send(
            new ChatMessage('Job completed!'),
            $event->user->device_token,
            (new AndroidNotification())
                ->priority('high')
                ->title('Job Status')
        );
    });
    

Advanced Patterns

  1. Dynamic Payloads Use closures or factories to generate payloads:

    $message = new ChatMessage('Order updated');
    $message->options(
        (new AndroidNotification())
            ->title('Order #' . $order->id)
            ->body('Status: ' . $order->status)
            ->data(['order_id' => $order->id])
    );
    
  2. Fallback for Unsupported Platforms Check platform before sending:

    if (str_starts_with($token, 'APA')) { // Android
        $message->options($androidOptions);
    } elseif (str_starts_with($token, 'c2s')) { // iOS
        $message->options($iosOptions);
    }
    
  3. Retry Logic Extend Symfony’s retry mechanism for Laravel:

    $transport = new Transport(
        new \Symfony\Component\Notifier\Transport\ChatTransport(
            'firebase://' . env('FIREBASE_DSN'),
            ['max_retries' => 3, 'delay' => 1000]
        )
    );
    

Gotchas and Tips

Pitfalls

  1. DSN Format Sensitivity

    • Issue: Incorrect DSN format (e.g., missing @default) causes silent failures.
    • Fix: Validate DSN with:
      if (!str_starts_with(env('FIREBASE_DSN'), 'firebase://')) {
          throw new \RuntimeException('Invalid Firebase DSN');
      }
      
  2. Firebase Credential Deprecation

    • Issue: Firebase no longer supports legacy XMPP credentials for new projects. Use service account JSON instead.
    • Workaround: Generate a DSN from a service account:
      $serviceAccount = json_decode(file_get_contents('path/to/service-account.json'), true);
      $dsn = sprintf(
          'firebase://%s:%s@%s',
          $serviceAccount['client_email'],
          $serviceAccount['private_key'],
          'default'
      );
      
  3. Payload Size Limits

    • Issue: Firebase FCM limits payloads to 4KB. Large data payloads may fail.
    • Fix: Use data payloads for critical info and deep links for the rest:
      $message->options(
          (new AndroidNotification())
              ->data(['large_data' => json_encode($data)])
              ->clickAction('OPEN_DEEP_LINK')
      );
      
  4. Token Expiration

    • Issue: Device tokens expire or change. Retry logic may not catch this.
    • Fix: Implement token refresh logic in your app:
      try {
          $transport->send($message, $token);
      } catch (\Symfony\Component\Notifier\Exception\TransportException $e) {
          if ($e->getCode() === 401) { // Unauthorized (invalid token)
              $token = $this->refreshDeviceToken($user);
              retry($transport->send($message, $token), 3);
          }
      }
      
  5. Platform-Specific Quirks

    • Android: Requires priority (high/normal) for notifications to appear.
    • iOS: Needs badge, sound, and content-available for silent pushes.
    • Web: Limited to notification payload type; use data for background sync.

Debugging Tips

  1. Enable Verbose Logging Configure Symfony’s Notifier to log raw payloads:

    $transport = new Transport(
        new \Symfony\Component\Notifier\Transport\ChatTransport(
            'firebase://' . env('FIREBASE_DSN'),
            ['debug' => true]
        )
    );
    

    Check logs for the exact payload sent to Firebase.

  2. Test with Firebase Console Use the Firebase Console to verify tokens and simulate notifications.

  3. Validate Tokens Ensure tokens are not empty or malformed:

    if (empty($token) || !preg_match('/^[a-zA-Z0-9\-_]{1,}$/', $token)) {
        throw new \InvalidArgumentException('Invalid FCM token');
    }
    

Extension Points

  1. Custom Notification Classes Extend AndroidNotification, IOSNotification, or WebNotification for project-specific options:

    class CustomAndroidNotification extends AndroidNotification
    {
        public function customAction(string $action): self
        {
            $this->data['custom_action'] = $action;
            return $this;
        }
    }
    
  2. Transport Decorators Wrap the transport to add

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.
craftcms/url-validator
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony