Cloud Messaging

You can use the Firebase Admin SDK for PHP to send Firebase Cloud Messaging messages to end-user devices. Specifically, you can send messages to individual devices, named topics, or condition statements that match one or more topics.

Note

Sending messages to Device Groups is only possible with legacy protocols which are not supported by this SDK.

Before you start, please read about Firebase Remote Config in the official documentation:

Getting started

After having initialized your Firebase project instance, you can access the Cloud Messaging component with $firebase->getMessaging().

use Kreait\Firebase;

$firebase = (new Firebase\Factory())->create();
$messaging = $firebase->getMessaging();

$messaging->send($message);

A message must be an object implementing Kreait\Firebase\Messaging\Message or an array that can be parsed to one of the supported message types.

The Supported message types are:

  • A message to a given topic Kreait\Firebase\Messaging\MessageToTopic
  • A conditional message Kreait\Firebase\Messaging\ConditionalMessage
  • A message to a specific device Kreait\Firebase\Messaging\MessageToRegistrationToken

A message can contain:

  • A notification Kreait\Firebase\Messaging\Notification
  • Arbitrary data as an array of key-value pairs where all keys and values are strings
  • Target platform specific configuration

Send messages to topics

Based on the publish/subscribe model, FCM topic messaging allows you to send a message to multiple devices that have opted in to a particular topic. You compose topic messages as needed, and FCM handles routing and delivering the message reliably to the right devices.

For example, users of a local weather forecasting app could opt in to a “severe weather alerts” topic and receive notifications of storms threatening specified areas. Users of a sports app could subscribe to automatic updates in live game scores for their favorite teams.

Some things to keep in mind about topics:

  • Topic messaging supports unlimited topics and subscriptions for each app.
  • Topic messaging is best suited for content such as news, weather, or other publicly available information.
  • Topic messages are optimized for throughput rather than latency. For fast, secure delivery to single devices or small groups of devices, target messages to registration tokens, not topics.

You can create a message to a topic in one of the following ways:

use Kreait\Firebase\Messaging\CloudMessage;

$topic = 'a-topic';

$message = CloudMessage::withTarget('topic', $topic)
    ->withNotification($notification) // optional
    ->withData($data) // optional
;

$message = CloudMessage::fromArray([
    'topic' => $topic,
    'notification' => [/* Notification data as array */], // optional
    'data' => [/* data array */], // optional
]);

$messaging->send($message);

Send conditional messages

Sometimes you want to send a message to a combination of topics. This is done by specifying a condition, which is a boolean expression that specifies the target topics. For example, the following condition will send messages to devices that are subscribed to TopicA and either TopicB or TopicC:

"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"

FCM first evaluates any conditions in parentheses, and then evaluates the expression from left to right. In the above expression, a user subscribed to any single topic does not receive the message. Likewise, a user who does not subscribe to TopicA does not receive the message. These combinations do receive it:

  • TopicA and TopicB
  • TopicA and TopicC
use Kreait\Firebase\Messaging\CloudMessage;

$condition = "'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)";

$message = CloudMessage::withTarget('condition', $condition)
    ->withNotification($notification) // optional
    ->withData($data) // optional
;

$message = CloudMessage::fromArray([
    'condition' => $condition,
    'notification' => [/* Notification data as array */], // optional
    'data' => [/* data array */], // optional
]);

$messaging->send($message);

Send messages to specific devices

The Admin FCM API allows you to send messages to individual devices by specifying a registration token for the target device. Registration tokens are strings generated by the client FCM SDKs for each end-user client app instance.

Each of the Firebase client SDKs are able to generate these registration tokens: iOS, Android, Web, C++, and Unity.

use Kreait\Firebase\Messaging\CloudMessage;

$deviceToken = '...';

$message = CloudMessage::withTarget('token', $deviceToken)
    ->withNotification($notification) // optional
    ->withData($data) // optional
;

$message = CloudMessage::fromArray([
    'token' => $deviceToken,
    'notification' => [/* Notification data as array */], // optional
    'data' => [/* data array */], // optional
]);

$messaging->send($message);

Adding a notification

A notification is an instance of Kreait\Firebase\Messaging\Notification and can be created in one of the following ways. The title and the body of a notification are both optional.

use Kreait\Firebase\Messaging\Notification;

$title = 'My Notification Title';
$body = 'My Notification Body';

$notification = Notification::fromArray([
    'title' => $title,
    'body' => $body
]);

$notification = Notification::create($title, $body);

$notification = Notification::create()
    ->withTitle($title)
    ->withBody($body);

Once you have created a message with one of the methods described below, you can attach the notification to it:

$message = $message->withNotification($notification);

Adding data

The data attached to a message must be an array of key-value pairs where all keys and values are strings.

Once you have created a message with one of the methods described below, you can attach data to it:

$data = [
    'first_key' => 'First Value',
    'second_key' => 'Second Value',
];

$message = $message->withData($data);

Changing the message target

You can change the target of an already created message with the withChangedTarget() method.

use Kreait\Firebase\Messaging\CloudMessage;

$deviceToken = '...';
$anotherDeviceToken = '...';

$message = CloudMessage::withTarget('token', $deviceToken)
    ->withNotification(['title' => 'My title', 'body' => 'My Body')
;

$messaging->send($message);

$sameMessageToDifferentTarget = $message->withChangedTarget('token', $anotherDeviceToken);

Adding target platform specific configuration

You can target platforms specific configuration to your messages.

Android

You can find the full Android configuration reference in the official documentation: REST Resource: projects.messages.AndroidConfig

use Kreait\Firebase\Messaging\AndroidConfig;

// Example from https://firebase.google.com/docs/cloud-messaging/admin/send-messages#android_specific_fields
$config = AndroidConfig::fromArray([
    'ttl' => '3600s',
    'priority' => 'normal',
    'notification' => [
        'title' => '$GOOG up 1.43% on the day',
        'body' => '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
        'icon' => 'stock_ticker_update',
        'color' => '#f45342',
    ],
]);

$message = $message->withAndroidConfig($config);

APNs

You can find the full APNs configuration reference in the official documentation: REST Resource: projects.messages.ApnsConfig

use Kreait\Firebase\Messaging\ApnsConfig;

// Example from https://firebase.google.com/docs/cloud-messaging/admin/send-messages#apns_specific_fields
$config = ApnsConfig::fromArray([
    'headers' => [
        'apns-priority' => '10',
    ],
    'payload' => [
        'aps' => [
            'alert' => [
                'title' => '$GOOG up 1.43% on the day',
                'body' => '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
            ],
            'badge' => 42,
        ],
    ],
]);

$message = $message->withApnsConfig($config);

WebPush

You can find the full WebPush configuration reference in the official documentation: REST Resource: projects.messages.Webpush

use Kreait\Firebase\Messaging\WebPushConfig;

// Example from https://firebase.google.com/docs/cloud-messaging/admin/send-messages#webpush_specific_fields
$config = ApnsConfig::fromArray([
    'notification' => [
        'title' => '$GOOG up 1.43% on the day',
        'body' => '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
        'icon' => 'https://my-server/icon.png',
    ],
]);

$message = $message->withWebPushConfig($config);

Sending a fully configured raw message

Note

The message will be parsed and validated by the SDK.

$firebase
    ->getMessaging()
    ->send([
        'topic' => 'my-topic',
        // 'condition' => "'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)",
        // 'token' => '...',
        'notification' => [
            'title' => 'Notification title',
            'body' => 'Notification body',
        ],
        'data' => [
            'key_1' => 'Value 1',
            'key_2' => 'Value 2',
        ],
        'android' => [
            'ttl' => '3600s',
            'priority' => 'normal',
            'notification' => [
                'title' => '$GOOG up 1.43% on the day',
                'body' => '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
                'icon' => 'stock_ticker_update',
                'color' => '#f45342',
            ],
        ],
        'apns' => [
            'headers' => [
                'apns-priority' => '10',
            ],
            'payload' => [
                'aps' => [
                    'alert' => [
                        'title' => '$GOOG up 1.43% on the day',
                        'body' => '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
                    ],
                    'badge' => 42,
                ],
            ],
        ],
        'webpush' => [
            'notification' => [
                'title' => '$GOOG up 1.43% on the day',
                'body' => '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
                'icon' => 'https://my-server/icon.png',
            ],
        ],
    ])

Validating messages

You can validate a message by sending a validation-only request to the Firebase REST API. If the message is invalid, a KreaitFirebaseExceptionMessagingInvalidMessage exception is thrown, which you can catch to evaluate the raw error message(s) that the API returned.

use Kreait\Firebase\Exception\Messaging\InvalidMessage;

try {
    $firebase->getMessaging()->validate($message);
} catch (InvalidMessage $e) {
    print_r($e->errors());
}

Topic management

Subscribe to a topic

You can subscribe one or multiple devices to a topic by passing registration tokens to the subscribeToTopic() method.

$topic = 'my-topic';
$registrationTokens = [
    // ...
};

$firebase
    ->getMessaging()
    ->subscribeToTopic($topic, $registrationTokens);

Note

You can subscribe up to 1,000 devices in a single request. If you provide an array with over 1,000 registration tokens, the operation will fail with an error.

Unsubscribe from a topic

You can unsubscribe one or multiple devices from a topic by passing registration tokens to the unsubscribeFromTopic() method.

$topic = 'my-topic';
$registrationTokens = [
    // ...
};

$firebase
    ->getMessaging()
    ->unsubscribeFromTopic($topic, $registrationTokens);

Note

You can unsubscribe up to 1,000 devices in a single request. If you provide an array with over 1,000 registration tokens, the operation will fail with an error.