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

Gcm Laravel Package

laravel-notification-channels/gcm

Laravel notification channel for sending push notifications through Google Cloud Messaging (GCM). It integrates GCM with Laravel’s notification system, letting you deliver mobile push messages through a dedicated channel.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install and register

composer require laravel-notification-channels/gcm

On Laravel 5.5+ the NotificationChannels\Gcm\GcmServiceProvider is auto-discovered. On older versions add it to config/app.php under providers.

2. Publish and configure

php artisan vendor:publish --provider="NotificationChannels\Gcm\GcmServiceProvider"

This writes config/gcm.php. Put your GCM/FCM legacy server key in GCM_KEY in .env (the package reads it from config, so never hardcode it). The key is sent as the Authorization: key=... header against Google's legacy gcm/send endpoint.

3. Teach your notifiable how to resolve a device token

// app/Models/User.php
public function routeNotificationForGcm()
{
    return $this->gcm_token;              // single token
    // return $this->devices->pluck('token')->all(); // multiple tokens
}

4. Send your first notification

use NotificationChannels\Gcm\GcmChannel;
use NotificationChannels\Gcm\GcmMessage;

class OrderShipped extends Notification
{
    public function via($notifiable)
    {
        return [GcmChannel::class];
    }

    public function toGcm($notifiable)
    {
        return GcmMessage::create()
            ->title('Order shipped')
            ->body("Order #{$this->order->id} is on its way")
            ->data(['order_id' => (string) $this->order->id]);
    }
}

Then $user->notify(new OrderShipped($order));. If nothing arrives, check in this order: (a) is GCM_KEY set and is config cached with the old value, (b) does routeNotificationForGcm() return a non-empty string, (c) does the device actually hold that registration token.

Where to look first: the package's src/GcmMessage.php is the whole API surface — read it before anything else. It is a small, single-purpose package (52 stars, last release 2017-08-10, archived), so the source is the documentation.

Implementation Patterns

Notification vs. data messages. The most important design decision with this package:

  • If you set title()/body(), GCM delivers a notification message — the OS draws the tray entry itself when the app is backgrounded, and your onMessageReceived handler is not called.
  • If you only call data([...]), it is a data message — your Android code always receives it, but you must build the notification manually.

Mixing both (title/body + data) is the common and recommended pattern: the tray entry is free, and the data payload is available when the user taps through.

Fan-out to multiple devices. Returning an array from routeNotificationForGcm() sends all tokens in one request (legacy GCM accepts up to 1000 registration IDs per call). For an account with many devices, prefer storing tokens in their own table with user_id, token, platform, last_seen_at, and prune aggressively:

public function routeNotificationForGcm()
{
    return $this->pushTokens()->pluck('token')->all();
}

Model the payload once. Keep a base notification or a small builder so title/icon/sound/priority stay consistent across the app:

abstract class PushNotification extends Notification
{
    public function via($notifiable) { return [GcmChannel::class]; }

    protected function base(): GcmMessage
    {
        return GcmMessage::create()
            ->icon('ic_notification')
            ->sound('default')
            ->priority('high');
    }
}

Queue everything. GCM sends are HTTP calls in the request path. Implement ShouldQueue on the notification (or use Notification::send from a job). Add ->timeToLive() when the message is only useful briefly (e.g. "driver is 2 minutes away") and ->priority('high') when it must punch through Doze.

Combine channels. via() is the natural feature-flag point — return [GcmChannel::class, MailChannel::class] only for users who have a token, and [MailChannel::class] otherwise. Returning null from toGcm() is the documented way to skip a push for a single recipient without touching via().

Prune dead tokens on response. The legacy API returns per-token results, and stale tokens come back as NotRegistered / InvalidRegistration. The package surfaces send failures via NotificationChannels\Gcm\Exceptions\CouldNotSendNotification, but per-token errors inside a batch response are your responsibility — hook the send path (a listener, or a thin wrapper service around $notifiable->notify()) and delete tokens that come back dead. Also handle canonical_ids: Google tells you the token has rotated, and you should replace the stored value or you will keep sending to the old one.

Test with fakes, not HTTP.

Notification::fake();
$user->notify(new OrderShipped($order));
Notification::assertSentTo($user, OrderShipped::class, function ($n, $channels) {
    return in_array(GcmChannel::class, $channels);
});

Unit-test payload construction directly by instantiating the notification and asserting on the GcmMessage getters — that is far cheaper than faking the client.

Integration tip: because the package is archived, wrap it. Put GcmChannel behind your own PushSender interface with one send(User $user, PushPayload $payload) method, so a future move to FCM (or Laravel's own fcm channel ecosystem) is a one-class change rather than a grep across every notification.

Gotchas and Tips

  • GCM is dead. Google shut down the GCM legacy endpoint; FCM is the successor and (for a period) accepted the same legacy server key and wire format. This package is archived and will not be updated. Treat it as a stopgap and plan the migration; the config key is literally the FCM legacy server key for most people still running it.
  • 4 KB payload ceiling. Data values must be strings — legacy GCM rejects nested objects/arrays and non-string scalars in the data block. ['order_id' => (string) $id], not ['order_id' => $id]. Serialize anything structured with json_encode before it goes in.
  • Config caching bites. After changing GCM_KEY, run php artisan config:clear (or re-run config:cache). A 401 InvalidRegistration/auth failure after a key rotation is almost always a stale cached config.
  • via() must name the channel class (GcmChannel::class). The string 'gcm' only works if the channel is registered under that alias — don't assume.
  • Returning null from toGcm() skips the push. Useful, but silent: if pushes "just stop" for one user, log when you return null.
  • Empty token arrays throw or no-op depending on version. Guard in routeNotificationForGcm() with a ->filter()->values() and skip early.
  • Notification messages are invisible to your handler in background. If a developer swears "the push never arrives", check whether they set title()/body() — the tray shows it, but onMessageReceived was never called. This is the single most common bug report with this package.
  • No automatic token lifecycle. Token rotation, canonical ID updates, and pruning are entirely on you. Build the prune job before you ship, not after your error rate climbs.
  • Debug by dumping the message, not the HTTP call. In tinker: (new OrderShipped($order))->toGcm($user) and inspect the resulting GcmMessage — confirms the payload shape without touching Google.
  • Extension point: the service provider binds the client used by the channel. If you need to swap the endpoint (pointing at a local fake, or at FCM), that container binding is the seam — but since the package is archived, prefer forking over monkey-patching bindings.
  • Don't install this on a greenfield project. With 0 dependents and no releases since 2017, the correct assessment is: it is a readable reference implementation of a Laravel notification channel, not a dependency to adopt.
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.
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core