Weave 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 Notification Bundle Laravel Package

jp/firebase-notification-bundle

Symfony bundle for sending Firebase Cloud Messaging push notifications from PHP apps. Configure credentials through bundle config, then dispatch messages to devices and topics with simple service calls, keeping FCM payload and device-token handling out of your controllers.

View on GitHub
Deep Wiki
Context7

Getting Started

Start by confirming it is not a Laravel package. jp/firebase-notification-bundle is a Symfony2 bundle — it ships a Bundle subclass and a DependencyInjection\Extension, not a ServiceProvider. Laravel does not boot the FrameworkBundle, so there is no auto-discovery, no config/packages/*.yaml, no facade. Do not composer require it into a Laravel app: it will conflict on symfony/dependency-injection / symfony/http-kernel against the Symfony 6/7 components Laravel already pulls, and the PHP pins are Symfony2-era. Treat it as source to read, not a dependency to install.

Where to look first. Open src/ and find the class that builds the payload and issues the HTTP call — usually a Sender/Client/Firebase service plus its DI definition in Resources/config/services.yml. Two things decide everything:

  1. The endpoint string. If it hits https://fcm.googleapis.com/fcm/send with an Authorization: key=<server-key> header, it targets the legacy FCM HTTP API, which Google shut down in mid-2024. At that point the package is function-dead and you are extracting-and-porting, not adopting.
  2. The PHP/Symfony constraints in composer.json, and whether it depends on google/apiclient. This tells you how much OAuth2 plumbing you'd have to add yourself.

First use case (the only viable one in Laravel). Port the ~50 lines of payload construction and the send call into a plain class — App\Services\FirebaseNotifier — and register it in an App\Providers\NotificationServiceProvider. Replace the Symfony YAML config tree with a config/firebase.php array. Prerequisite: an FCM HTTP v1 service-account JSON, not a legacy server key. Validate the whole path with a one-message spike before building anything around it.

Implementation Patterns

Extract behind an interface, not a package. Define App\Contracts\PushGateway with a send(DeviceToken|Topic, Payload): DeliveryResult method, and implement it with the extracted logic. This is the pattern that makes the rest of the assessment sane: FCM-specific code lives at the boundary, and swapping to kreait/laravel-firebase or laravel-notification-channels/fcm later is a config change.

Config pattern. A flat config/firebase.php returning project_id, credentials_path (env-driven, never committed), and sane defaults. Cache it with php artisan config:cache like any other Laravel config — the Symfony extension tree does not map 1:1, so translate explicitly rather than copying YAML keys.

Auth is yours to add. HTTP v1 needs an OAuth2 bearer token minted from the service account (scope https://www.googleapis.com/auth/firebase.messaging). Use google/auth or kreait to mint and cache the token for ~55 minutes — minting per send is the most common performance mistake in hand-rolled wrappers.

Device vs. topic sends. Keep them as distinct methods on the gateway, not a $to string with a /topics/ prefix. v1 uses message.topic for topics and message.token for single devices; conflating them produces silent 400s.

Wire it into Laravel's ergonomics. The day-to-day payoff is a custom NotificationChannel so product code writes $user->notify(new OrderShipped($order)) and never touches FCM. The channel resolves tokens, calls the gateway, and records the result. Keep payload DTOs framework-agnostic.

Queue by default. The bundle-era code sends inline during the request. Move every send to a ShouldQueue job, and chunk multicasts (v1 caps per-send device counts; treat batches of ~500 as the ceiling). A broadcast to 100k devices must never sit in a web request.

Test against a fake gateway. Assert payload shape and error handling with a bound fake PushGateway; mock the transport, not the network. There is no useful test suite upstream — you own coverage.

Gotchas and Tips

  • Do not install in a Laravel project. Composer conflicts on Symfony components and EOL PHP pins are the first wall; nothing runs even if resolution succeeds.
  • HTTP 200 does not mean delivered. Legacy FCM returned 200 OK with an error code in the response body (MismatchSenderId, NotRegistered, etc.). Naive if ($response->isSuccessful()) drops messages silently. The extracted logic must parse the body.
  • Prune stale tokens. UNREGISTERED / INVALID_ARGUMENT per-token errors are the signal to delete the token row; without pruning, deliverability metrics drift and send cost rises on dead tokens.
  • Respect 429 and Retry-After. Per-project rate limits are real; chunk multicasts and apply exponential backoff in the queued job rather than hammering the endpoint.
  • Legacy credentials are dead. A server key will now fail with a 401 at send time, not at deploy. Migrate to a service-account JSON before touching production.
  • Config translation is manual. Symfony's Extension::load() tree does not survive the port; do not try to preserve its shape. Model a small, explicit Laravel config array instead.
  • Payload limits. ~4KB total; all data values must be strings. Enforce this in the DTO, not at the FCM boundary.
  • No observability upstream. Assume zero logging or metrics — wrap the gateway with counters for sent, accepted, rejected, and pruned, and log the FCM name (message ID) so support can trace delivery.
  • Extension points worth keeping. The only genuinely reusable artifact is the sender class and payload builder. Treat the DI registration, YAML config, and README as disposable.
  • Legacy coexistence option. If a Symfony2 service already depends on this bundle and Laravel must talk to it, expose it behind an internal HTTP endpoint and call it with Http::withToken(...) — cheaper than porting sender logic that will be obsolete anyway.
  • Verdict for day-to-day use: as a reference implementation, yes; as a dependency, no. Extract the send logic, back it with a maintained HTTP v1 client, and keep FCM-specific code behind PushGateway so the next framework generation is a config swap, not a rewrite.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource