---
source_url: https://www.pubnub.com/docs/sdks/php/api-reference/publish-and-subscribe
title: Publish/Subscribe API for PHP SDK
updated_at: 2026-06-04T11:12:30.881Z
sdk_name: PubNub PHP SDK
sdk_version: 9.0.0
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Publish/Subscribe API for PHP SDK

PubNub PHP SDK, use the latest version: 9.0.0

Install:

```bash
composer require pubnub/pubnub@9.0.0
```

PubNub delivers messages worldwide in less than 30 ms. Send a message to one recipient or broadcast to thousands of subscribers.

For higher-level conceptual details on publishing and subscribing, refer to [Connection Management](https://www.pubnub.com/docs/general/setup/connection-management) and to [Publish Messages](https://www.pubnub.com/docs/general/messages/publish).

## Publish

`publish()` sends a message to all channel subscribers. PubNub replicates the message across its points of presence and delivers it to all subscribed clients on that channel.

### Prerequisites and limitations

* You must [initialize PubNub](https://www.pubnub.com/docs/sdks/php/api-reference/configuration#configuration) with the `publishKey`.
* You don't have to be subscribed to a channel to publish to it.
* You cannot publish to multiple channels simultaneously.

### Security

Secure messages with Transport Layer Security (TLS) or Secure Sockets Layer (SSL) by setting `ssl` to `true` during [initialization](https://www.pubnub.com/docs/sdks/php/api-reference/configuration). You can also [encrypt](https://www.pubnub.com/docs/sdks/php/api-reference/configuration#crypto-module) messages.

### Message data

The message can contain any JavaScript Object Notation (JSON)-serializable data (objects, arrays, integers, strings). Avoid special classes or functions. Strings can include any UTF‑8 characters.

:::warning Don't JSON serialize
You should not JSON serialize the `message` and `meta` parameters when sending signals, messages, or files as the serialization is automatic. Pass the full object as the message/meta payload and let PubNub handle everything.
:::

### Size

The maximum message size is 32 KiB. This includes the escaped character count and the channel name. Aim for under 1,800 bytes for optimal performance.

If your message exceeds the limit, you'll receive a `Message Too Large` error. To learn more or calculate payload size, see [Message size limits](https://www.pubnub.com/docs/general/messages/publish#message-size-limit).

:::tip Need larger messages?
Our platform is optimized for payloads up to 32 KiB. PubNub supports larger messages, but increasing the limit requires a verification of compatibility with your use case.
Talk to [our team](https://www.pubnub.com/company/contact-sales/) to discuss increasing the message size limit for your use case.
:::

### Publish rate

You can publish as fast as bandwidth allows. There is a [soft throughput limit](https://www.pubnub.com/docs/general/setup/limits) because messages may drop if subscribers can't keep up.

For example, publishing 200 messages at once may cause the first 100 to drop if a subscriber hasn't received any yet. The in-memory queue stores only 100 messages.

### Custom message type

You can optionally provide the `customMessageType` parameter to add your business-specific label or category to the message, for example `text`, `action`, or `poll`.

### Best practices

* Publish to a channel serially (not concurrently).
* Verify a success return code (for example, `[1,"Sent","136074940..."]`).
* Publish the next message only after a success return code.
* On failure (`[0,"blah","<timetoken>"]`), retry.
* Keep the in-memory queue under 100 messages to avoid drops.
* Throttle bursts to meet latency needs (for example, no more than 5 messages per second).

### Method(s)

To `Publish a message` you can use the following method(s) in the PHP SDK:

```php
$pubnub->publish()
    ->channel(string)
    ->message(string|array)
    ->shouldStore(boolean)
    ->ttl($ttl)
    ->meta(array)
    ->usePost(boolean)
    ->customMessageType(string)
    ->sync();
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channel | String | Yes |  | Destination of `message` (channel ID). |
| message | String|Array | Yes |  | The payload. |
| shouldStore | Boolean | Optional | `account default` | Store in history. |
| ttl | Number | Optional |  | Set a per message time to live in Message Persistence. If shouldStore = true, and ttl = 0, the message is stored with no expiry time., If shouldStore = true and ttl = X (X is an Integer value), the message is stored with an expiry time of X hours unless you have message retention set to Unlimited on your keyset configuration in the Admin Portal., If shouldStore = false, the ttl parameter is ignored., If ttl is not specified, then expiration of the message defaults back to the expiry value for the key. |
| meta | Array | Optional | `null` | `Meta` data object which can be used with the filtering ability. |
| usePost | Boolean | Optional | `false` | Use POST to `publish`. |
| customMessageType | string | Optional |  | A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes `-` and underscores `_` are allowed. The value cannot start with special characters or the string `pn_` or `pn-`. Examples: `text`, `action`, `poll`. |

### Sample code

#### Publish a message to a channel

:::tip Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
:::

```php
<?php

// Include Composer autoloader (adjust path if needed)
require_once 'vendor/autoload.php';

use PubNub\PNConfiguration;
use PubNub\PubNub;
use PubNub\Exceptions\PubNubServerException;
use PubNub\Exceptions\PubNubException;

// snippet.publish_complete
// Create configuration with demo keys
$pnConfig = new PNConfiguration();
$pnConfig->setSubscribeKey(getenv("SUBSCRIBE_KEY") ?? "demo");
$pnConfig->setPublishKey(getenv("PUBLISH_KEY") ?? "demo");
$pnConfig->setUserId("php-publisher-demo");

// Initialize PubNub instance
$pubnub = new PubNub($pnConfig);

try {
    // Create message data
    $messageData = [
        "text" => "Hello from PHP SDK!",
        "timestamp" => time(),
        "sender" => [
            "name" => "PHP Publisher",
            "id" => "php-demo"
        ]
    ];

    // Publish a message to a channel
    $result = $pubnub->publish()
        ->channel("hello_world")              // Channel to publish to
        ->message($messageData)               // Message content
        ->shouldStore(true)                   // Store in history
        ->ttl(15)                             // Time to live (hours)
        ->usePost(true)                       // Use POST method
        ->customMessageType("text-message")   // Custom message type
        ->sync();                             // Execute synchronously

    // Display success message with timetoken
    echo "Message published successfully!" . PHP_EOL;
    echo "Timetoken: " . $result->getTimetoken() . PHP_EOL;

    // Convert timetoken to readable date
    $timestamp = floor($result->getTimetoken() / 10000000);
    $readableDate = date('Y-m-d H:i:s', $timestamp);
    echo "Published at: " . $readableDate . PHP_EOL;

    // Display published message
    echo PHP_EOL . "Published message: " . PHP_EOL;
    echo json_encode($messageData, JSON_PRETTY_PRINT) . PHP_EOL;
} catch (PubNubServerException $exception) {
    // Handle PubNub server-specific errors
    echo "Error publishing message: " . $exception->getMessage() . PHP_EOL;

    if (method_exists($exception, 'getServerErrorMessage') && $exception->getServerErrorMessage()) {
        echo "Server Error: " . $exception->getServerErrorMessage() . PHP_EOL;
    }

    if (method_exists($exception, 'getStatusCode') && $exception->getStatusCode()) {
        echo "Status Code: " . $exception->getStatusCode() . PHP_EOL;
    }
} catch (PubNubException $exception) {
    // Handle PubNub-specific errors
    echo "PubNub Error: " . $exception->getMessage() . PHP_EOL;
} catch (Exception $exception) {
    // Handle general exceptions
    echo "Error: " . $exception->getMessage() . PHP_EOL;
}
// snippet.end
```

:::note Subscribe to the channel
Before running the above publish example, either using the [Debug Console](https://www.pubnub.com/docs/console/) or in a separate script running in a separate terminal window, [subscribe to the same channel](#subscribe) that is being published to.
:::

### Response

The `publish()` operation returns a `PNPublishResult` which contains the following fields:

| Property Name | Type | Description |
| --- | --- | --- |
| `getTimetoken()` | Integer | An `integer` representation of the timetoken when the message was published. |

### Other examples

#### Publish with metadata

```php
$result = $pubnub->publish()
    ->channel("my_channel")
    ->message(["text" => "Message with meta"])
    ->meta(["custom" => "metadata"])
    ->sync();
assert($result->getTimetoken() > 0);
echo "Publish with meta timetoken: {$result->getTimetoken()}\n";
```

#### Publish array

```php
try {
    $result = $pubnub->publish()
        ->channel("my_channel")
        ->message(["hello", "there"])
        ->meta(["name" => "Alex", "online" => true])
        ->sync();
    print_r($result->getTimetoken());
} catch (PubNubException $error) {
    echo "Error: " . $error->getMessage() . "\n";
}
```

## Fire

The fire endpoint sends a message to Functions event handlers and [Illuminate](https://www.pubnub.com/docs/illuminate/business-objects/external-data-sources). The message goes directly to handlers registered on the target channel and triggers their execution. The handler can read the request body. Messages sent via `fire()` aren't replicated to subscribers and aren't stored in history.

### Method(s)

To `Fire a message` you can use the following method(s) in the PHP SDK:

```php
$pubnub->fire()
    ->channel(string)
    ->message(string|array)
    ->meta(array)
    ->usePost(boolean)
    ->sync();
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: StringDefault: n/a | Destination of `message` (channel ID). |
| `message` *Type: String|ArrayDefault: n/a | The payload. |
| `meta`Type: ArrayDefault: `null` | `Meta` data object which can be used with the filtering ability. |
| `usePost`Type: BooleanDefault: `false` | Use POST to `publish`. |

### Sample code

#### Fire a message to a channel

```php
$result = $pubnub->fire()
    ->channel("my_channel")
    ->message(["text" => "Fire message"])
    ->sync();
assert($result->getTimetoken() > 0);
echo "Fire timetoken: {$result->getTimetoken()}\n";
```

## Signal

The `signal()` function sends a signal to all subscribers of a channel.

### Prerequisites and limitations

* You must [initialize PubNub](https://www.pubnub.com/docs/sdks/php/api-reference/configuration#configuration) with the `publishKey`.
* The message payload size (without the URI or headers) is limited to `64` bytes. If you require a larger payload size, [contact support](https://www.pubnub.com/docs/mailto:support@pubnub.com).

### Signal vs. Message

| **Feature** | **Signals** | **Messages** |
| --- | --- | --- |
| **Payload size** | Limited to 64 bytes (64B) | Up to 32 KiB |
| **Cost efficiency** | Cost less than standard messages | Generally more expensive than signals |
| **Persistence** | Cannot be saved in [Message Persistence](https://www.pubnub.com/docs/sdks/php/api-reference/storage-and-playback) (past signals cannot be accessed) | Can be saved and accessed through Message Persistence |
| **Push Notifications** | Cannot trigger [Mobile Push Notifications](https://www.pubnub.com/docs/sdks/php/api-reference/mobile-push) | Can trigger Mobile Push Notifications |
| **Use case suitability** | Best for non-critical data streams, like geolocation updates | Suitable for critical and non-critical use cases |
| **Metadata support** | Do not support metadata | Support metadata |

:::note Channel separation
Signals and messages should be sent on separate channels to improve connection recovery behaviour.
:::

### Method(s)

To `Send a signal` you can use the following method(s) in the PHP SDK:

```php
$pubnub->signal()
    ->channel(string)
    ->message(string|array)
    ->sync();
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: String | The channel ID to send the signal to. |
| `message` *Type: String|Array | The signal message payload. |

### Sample code

#### Send a signal to a channel

```php
$result = $pubnub->signal()
    ->channel("my_channel")
    ->message(["text" => "Signal message"])
    ->sync();
assert($result->getTimetoken() > 0);
echo "Signal timetoken: {$result->getTimetoken()}\n";
```

### Response

The `signal()` operation returns a `PNSignalResult` which contains the following fields:

| Property Name | Type | Description |
| --- | --- | --- |
| `getTimetoken()` | int | An `int` representation of the timetoken when the signal was sent. |

## Subscribe

### Receive messages

Your app receives messages and events via event listeners. The event listener is a single point through which your app receives all the messages, signals, and events that are sent in any channel you are subscribed to.

For more information about adding a listener, refer to the [Event Listeners](https://www.pubnub.com/docs/sdks/php/api-reference/configuration#event-listeners) section.

:::note No built-in event throttling
The PubNub SDK delivers every incoming event to your listener as it arrives — there is no built-in throttling or rate-limiting on the subscriber side. If you need to control how often your application processes events, wrap your listener callback with a throttle or debounce utility from your language or framework ecosystem.
To reduce the number of messages delivered to your client in the first place, use [Subscribe Filters](https://www.pubnub.com/docs/general/channels/subscribe-filters) to filter messages server-side before they reach your listener.
:::

### Description

This function causes the client to create an open TCP socket to the PubNub Real-Time Network and begin listening for messages on a specified `channel` ID. To subscribe to a `channel` ID the client must send the appropriate `subscribeKey` at initialization.

By default a newly subscribed client will only receive messages published to the channel after the `subscribe()` call completes.

:::note Subscribe call is blocking and it will block until:
* A message is published on the channel(s) it is subscribed to (`message` callback).
* A presence event is received on the channel(s) it is subscribed to (`presence` callabck).
* A status event is triggered by SDK (`status` callback).
Inside of all of the callbacks above you can throw `PubNubUnsubscribeException` to exit the subscribe loop.
:::

:::warning Unsubscribing from all channels
**Unsubscribing** from all channels, and then **subscribing** to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received `timetoken` and thus, there could be some gaps in the subscription that may lead to message loss.
:::

### Method(s)

To `Subscribe to a channel` you can use the following method(s) in the PHP SDK:

```php
$pubnub->subscribe()
    ->channels(string|array)
    ->channelGroups(string|array)
    ->withTimetoken(integer)
    ->withPresence(boolean)
    ->execute();
```

| Parameter | Description |
| --- | --- |
| `channels`Type: String or Array | Subscribe to `channels`, Either `channel` ID or `channel_group` is required. |
| `channelGroups`Type: String or Array | Subscribe to `channel_groups`, Either `channel` ID or `channel_group` is required. |
| `withTimetoken`Type: Integer | Pass a `timetoken`. |
| `withPresence`Type: Boolean | Also subscribe to related presence information. For information on how to receive presence events and what those events are, refer to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events#subscribe-to-presence-channel). |

### Sample code

Subscribe to a channel:

```php
$pubnub->subscribe()
    ->channels("my_channel")
    ->execute();
```

:::note Event listeners
The response of the call is handled by adding a Listener. Please see the [Listeners section](https://www.pubnub.com/docs/sdks/php#add-event-listeners) for more details. Listeners should be added before calling the method.
:::

### Response

PNStatus:

| Property Name | Type | Description |
| --- | --- | --- |
| `getCategory()` | `PNStatusCategory` | See the [PHP SDK status categories](https://www.pubnub.com/docs/sdks/php/status-events). |
| `isError()` | bool | This is `true` if an error occurred in the execution of the operation. |
| `getException()` | PubNubException | Error data of the exception (if `Error` is `true`). |
| `getStatusCode()` | int | Status code of the execution. |
| `Operation` | OperationType | Operation type of the request. |

PNMessageResult:

| Method | Description |
| --- | --- |
| `getMessage()`Type: Object | The message sent on the `channel` ID. |
| `getSubscription()`Type: String | The `channel` ID on which the message was received. |
| `getTimetoken()`Type: Integer | `Timetoken` for the message. |

PNPresenceEventResult:

| Method | Description |
| --- | --- |
| `getStatusCode()`Type: Integer | Events like `join`, `leave`, `timeout`, `state-change`. |
| `getUuid()`Type: String | `uuid` for event. |
| `getTimestamp()`Type: Integer | `timestamp` for event. |
| `getOccupancy()`Type: Integer | Current `occupancy`. |
| `getSubscription()`Type: String | Message has been received on the `channel` ID. |
| `getTimetoken()`Type: Integer | `timetoken` of the message. |

### Other examples

#### Basic subscribe with logging

```php
use Monolog\Handler\ErrorLogHandler;

$pnconf = new PNConfiguration();

$pnconf->setPublishKey("demo");
$pnconf->setSubscribeKey("demo");
$pnconf->setUserId("php-subscriber-with-logging");

$pubnub = new PubNub($pnconf);

$pubnub->getLogger()->pushHandler(new ErrorLogHandler());

$pubnub->subscribe()->channels("my_channel")->execute();
```

#### Subscribing to multiple channels

It's possible to subscribe to more than one channel using the [Multiplexing](https://www.pubnub.com/docs/general/channels/subscribe#channel-multiplexing) feature. The example shows how to do that using an array to specify the channel names.

:::note Alternative subscription methods
You can also use [Wildcard Subscribe](https://www.pubnub.com/docs/general/channels/subscribe#wildcard-subscribe) and [Channel Groups](https://www.pubnub.com/docs/general/channels/subscribe#channel-groups) to subscribe to multiple channels at a time. To use these features, the *Stream Controller* add-on must be enabled on your keyset in the [Admin Portal](https://admin.pubnub.com).
:::

```php
$pubnub->subscribe()
    ->channels(["my_channel1", "my_channel2"])
    ->execute();
```

#### Subscribing to a Presence channel

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/). For information on how to receive presence events and what those events are, refer to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events#subscribe-to-presence-channel).
:::

For any given channel there is an associated Presence channel. You can subscribe directly to the channel by appending `-pnpres` to the channel name. For example the channel named `my_channel` would have the presence channel named `my_channel-pnpres`.

```php
$pubnub->subscribe()
    ->channels("my_channel")
    ->withPresence()
    ->execute();
```

#### Sample Responses

##### Join event

```json
{
    "action": "join",
    "timestamp": 1345546797,
    "uuid": "175c2c67-b2a9-470d-8f4b-1db94f90e39e",
    "occupancy": 2
}
```

##### Leave event

```json
{
    "action" : "leave",
    "timestamp" : 1345549797,
    "uuid" : "175c2c67-b2a9-470d-8f4b-1db94f90e39e",
    "occupancy" : 1
}
```

##### Timeout event

```json
{
    "action": "timeout",
    "timestamp": 1345549797,
    "uuid": "76c2c571-9a2b-d074-b4f8-e93e09f49bd",
    "occupancy": 0
}
```

##### Custom Presence event (state change)

```json
{
    "action": "state-change",
    "uuid": "76c2c571-9a2b-d074-b4f8-e93e09f49bd",
    "timestamp": 1345549797,
    "data": {
        "isTyping": true
    }
}
```

##### Interval event

```json
{
    "action":"interval",
    "timestamp":1474396578,
    "occupancy":2
}
```

When a channel is in interval mode with `presence_deltas` `pnconfig` flag enabled, the interval message may also include the following fields which contain an array of changed UUIDs since the last interval message.

* joined
* left
* timedout

For example, this interval message indicates there were 2 new UUIDs that joined and 1 timed out UUID since the last interval:

```json
{
    "action" : "interval",
    "occupancy" : <# users in channel>,
    "timestamp" : <unix timestamp>,
    "joined" : ["uuid2", "uuid3"],
    "timedout" : ["uuid1"]
}
```

If the full interval message is greater than `30 KB` (since the max publish payload is `∼32 KiB`), none of the extra fields will be present. Instead there will be a `here_now_refresh` boolean field set to `true`. This indicates to the user that they should do a `hereNow` request to get the complete list of users present in the channel.

```json
{
    "action" : "interval",
    "occupancy" : <# users in channel>,
    "timestamp" : <unix timestamp>,
    "here_now_refresh" : true
}
```

#### Wildcard subscribe to channels

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/) (with Enable Wildcard Subscribe checked). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

Wildcard subscribes allow the client to subscribe to multiple channels using wildcard. For example, if you subscribe to `a.*` you will get all messages for `a.b`, `a.c`, `a.x`. The wildcarded `*` portion refers to any portion of the channel string name after the `dot (.)`.

```php
$pubnub->subscribe()
    ->channels("foo.*")
    ->execute();
```

:::note Wildcard grants and revokes
Only one level (`a.*`) of wildcarding is supported. If you grant on `*` or `a.b.*`, the grant will treat `*` or `a.b.*` as a single channel named either `*` or `a.b.*`. You can also revoke permissions from multiple channels using wildcards but only if you previously granted permissions using the same wildcards. Wildcard revokes, similarly to grants, only work one level deep, like `a.*`.
:::

#### Subscribing with state

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/). For information on how to receive presence events and what those events are, refer to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events#subscribe-to-presence-channel).
:::

:::note Required UUID
Always set the `UUID` to uniquely identify the user or device that connects to PubNub. This `UUID` should be persisted, and should remain unchanged for the lifetime of the user or the device. If you don't set the `UUID`, you won't be able to connect to PubNub.
:::

```php
class MySubscribeCallbackWithState extends SubscribeCallback
{
    public function status($pubnub, $status)
    {
        if ($status->getCategory() === PNStatusCategory::PNConnectedCategory) {
            $result = $pubnub
                ->setState()
                ->channels("awesomeChannel")
                ->channelGroups("awesomeChannelGroup")
                ->state([
                    "fieldA" => "awesome",
                    "fieldB" => 10,
                ])
                ->sync();
            print_r($result);
        }
    }

    public function message($pubnub, $message)
    {
    }

    public function presence($pubnub, $presence)
    {
    }
}

$subscribeCallback = new MySubscribeCallbackWithState();

$pubnub->addListener($subscribeCallback);

$pubnub->subscribe()
    ->channels("my_channel")
    ->execute();
```

#### Subscribe to a channel group

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```php
$pubnub->subscribe()
    ->channelGroups(["cg1", "cg2"])
    ->execute();
```

#### Subscribe to the Presence channel of a channel group

:::note Requires Stream Controller and Presence add-ons
This method requires both the *Stream Controller* and *Presence* add-ons are enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```php
$pubnub->subscribe()
    ->channelGroups("awesome_channel_group")
    ->withPresence()
    ->execute();
```

## Unsubscribe

To unsubscribe you should throw `PubNubUnsubscribeException` somewhere inside `status`/`message`/`presence` callbacks of your subscribe listeners. You should specify channel and / or channel group names to unsubscribe and keep a subscription loop running if some other channels left. Otherwise the exception will unsubscribe from all channels and channel-groups.

### Method(s)

To `Unsubscribe from a channel` you can use the following method(s) in the PHP SDK:

```php
(new PubNubUnsubscribeException())
    ->setChannels(array)
    ->setChannelGroups(array);
```

| Parameter | Description |
| --- | --- |
| `getChannels`Type: StringDefault: `false` | The `channels` to get the here now details. |
| `getChannelGroups`Type: StringDefault: `false` | The `channel groups` to get the here now details. |
| `setChannels`Type: ArrayDefault: `false` | Unsubscribe to channels, Either `channel` ID or `channelGroup` is required. |
| `setChannelGroups`Type: ArrayDefault: `false` | Unsubscribe to channel groups, Either `channel` ID or `channelGroup` is required. |

### Sample code

Unsubscribe from a channel:

```php
use PubNub\Exceptions\PubNubUnsubscribeException;

class MyUnsubscribeCallback extends SubscribeCallback
{
    public function status($pubnub, $status)
    {
        if ($this->checkUnsubscribeCondition()) {
            throw (new PubNubUnsubscribeException())->setChannels("awesomeChannel");
        }
    }

    public function message($pubnub, $message)
    {
    }

    public function presence($pubnub, $presence)
    {
    }

    public function checkUnsubscribeCondition()
    {
        // return true or false
        return false;
    }
}

$pnconfig = new PNConfiguration();

$pnconfig->setPublishKey("demo");
$pnconfig->setSubscribeKey("demo");
$pnconfig->setUserId("php-unsubscribe-demo");

$pubnub = new PubNub($pnconfig);

$subscribeCallback = new MyUnsubscribeCallback();

$pubnub->addListener($subscribeCallback);

$pubnub->subscribe()
    ->channels("awesomeChannel")
    ->execute();
```

### Rest response from server

The output below demonstrates the response to a successful call:

```json
{
    "action" : "leave"
}
```

### Other examples

#### Unsubscribing from multiple channels

:::note Requires Stream Controller add-on
This method requires that the *Stream Controller* add-on is enabled for your key in the [Admin Portal](https://admin.pubnub.com/). Read the [support page](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) on enabling add-on features on your keys.
:::

```php
class MyUnsubscribeMultipleCallback extends SubscribeCallback
{
    public function status($pubnub, $status)
    {
        if ($this->checkUnsubscribeCondition()) {
            throw (new PubNubUnsubscribeException())->setChannels(["channel1", "channel2", "channel3"]);
        }
    }

    public function message($pubnub, $message)
    {
    }

    public function presence($pubnub, $presence)
    {
    }

    public function checkUnsubscribeCondition()
    {
        return false;
    }
}
```

##### Example response

```json
{
    "action" : "leave"
}
```

#### Unsubscribe from a channel group

```php
class MyUnsubscribeChannelGroupCallback extends SubscribeCallback
{
    public function status($pubnub, $status)
    {
        if ($this->checkUnsubscribeCondition()) {
            throw (new PubNubUnsubscribeException())->setChannelGroups(["cg1", "cg2"]);
        }
    }

    public function message($pubnub, $message)
    {
    }

    public function presence($pubnub, $presence)
    {
    }

    public function checkUnsubscribeCondition()
    {
        return false;
    }
}
```

##### Example response

```javascript
{
    "action": "leave"
}
```

## Terms in this document

* **Access Manager** - A cryptographic, token-based permission administrator that allows you to regulate clients' access to PubNub resources, such as channels, channel groups, and user IDs.
* **Action** - The type of activity (procedure) to execute when a condition is satisfied (for example, sending a message).
* **Billing alert notification** - A means of informing a user that a billing alert has been triggered. Before notifications can happen, a billing alert must be triggered first.
* **Business Object** - A container for data fields and metrics that defines aggregations and data sources.
* **Channel** - A pathway for sending and receiving messages between devices, created automatically when you first use it, that can handle any number of users and messages for different communication needs, like 1-1 text chats, group conversations, and other data streaming.
* **Channel pattern** - A way to group and analyze channel data to track performance metrics like message counts and user engagement over time with PubNub Insights.
* **Condition** - A requirement that must be satisfied or evaluated to true for an action to be executed. Input in a decision table.
* **Cryptor** - An implementation of a specific cryptographic algorithm used for data encryption/decryption that adheres to a standard interface.
* **Dashboard** - A collection of widgets (charts) that give an overview of the metrics one is evaluating.
* **Data fields** - Data you want Illuminate to track. These can be quantitative (measures), like "Number" or "Timestamp" or qualitative (dimensions) values, like "String" that can be used to categorize and segment data. Data fields can be aggregated and calculated.
* **Decision** - A collection (or decision table) of conditions and actions. When conditions are satisfied, the corresponding actions are triggered as per defined rules.
* **End Customer** - A customer of a PubNub partner. End customers do not have direct access to the Admin Portal. Instead, they interact with PubNub products—such as Illuminate—through the partner’s portal, where PubNub services are embedded. They can create PubNub objects only within this partner-provided environment.
* **Entity** - A subscribable object within a PubNub SDK that allows you to perform context-specific operations.
* **Listener** - A function or objectthat reacts to events or messages, like new chat messages or connection updates, letting your app respond in real-time.
* **Mapped/Unmapped** - Whether the data source for a data field has been defined or the action has been configured.
* **MCP Server** - A Model Context Protocol server that coordinates communication and synchronization between AI agents, clients, or services, such as Cursor IDE and Windsurf.
* **Message** - A unit of data transmitted between clients or between a client and a server in PubNub, containing information such as text, binary data, or structured data formats like JSON. Messages are sent over channels and can be tracked for delivery and read status.
* **Metric** - What exactly is evaluated using measures and dimensions (collectively called data fields), as well as aggregation functions.
* **Module** - A Functions v1 container that groups related functions for configuration and deployment on an app’s keysets.
* **Origin** - The subdomain used to establish a connection to the PubNub network that allows your application's traffic to appear like it's coming from your own domain.
* **Package** - A Functions v2 container that groups Functions, tracks Revisions, and is deployed to keysets.
* **Partner** - A PubNub customer who resells PubNub products, such as Illuminate, to their own customers. Partners have access to the Admin Portal, enabling them to create and manage PubNub objects for themselves or on behalf of their end customers.
* **Publish Key** - A unique identifier that allows your application to send messages to PubNub channels. It's part of your app's credentials and should be kept secure.
* **PubNub** - PubNub is a real-time messaging platform that provides APIs and SDKs for building scalable applications. It handles the complex infrastructure of real-time communication, including: Message delivery and persistence, Presence detection, Access control, Push notifications, File sharing, Serverless processing with Functions and Events & Actions, Analytics and monitoring with BizOps Workspace, AI-powered insights with Illuminate.
* **Push token** - A device identifier issued by a push provider (APNs or FCM) used to register a device for receiving mobile push notifications.
* **Rule** - A definition (row in a decision table) stating which action should be triggered for which condition.
* **Service Integration** - A machine identity that represents a program or service consuming the Admin API, scoped to your account and authenticated using expirable API keys with configurable permissions.
* **Signal** - A non-persistent message limited to 64 bytes designed for high-volume usecases where the the most recent data is relevant, like GPS location updates.
* **Subscribe Key** - A unique identifier that allows your application to receive messages from PubNub channels. It's part of your app's credentials and should be kept secure.
* **Timetoken** - A unique identifier for each message that represents the number of 100-nanosecond intervals since January 1, 1970, for example, 16200000000000000.
* **Trigger details** - A set of predefined criteria for a given billing alert. When met, billing alert notifications are generated.
* **User** - An individual or entity that interacts with a system, application, or service. In PubNub, a user typically refers to someone who sends or receives messages through the platform, identified by a unique user ID or username.
* **User ID** - UTF-8 encoded, unique string of up to 92 characters used to identify a single client (end user, device, or server) that connects to PubNub.
* **Vibe Coding** - A way to build applications in an intuitive, relaxed, and improvisational manner, using AI tools and natural language descriptions.