Skip to content

RocketChat Notification Channel

Introduction

The RocketChat Notification Channel allows you to send notifications to RocketChat via incoming webhooks using the CakePHP Notification plugin. RocketChat is a free, open-source team collaboration platform that provides features like instant messaging, file sharing, and video conferencing.

This channel plugin provides:

  • Simple webhook-based integration with RocketChat
  • Rich message formatting with attachments, fields, and images
  • Support for multiple RocketChat instances
  • Fluent API for building complex messages
  • Full integration with CakePHP's Notification system

Installation

Requirements

  • PHP 8.1 or higher
  • CakePHP 5.0 or higher
  • CakePHP Notification Plugin

Installation via Composer

Install the plugin using composer:

bash
composer require skie/notification-rocketchat

Load the Plugin

Add the plugin to your CakePHP application in src/Application.php:

php
<?php
namespace App;

use Cake\Http\BaseApplication;

class Application extends BaseApplication
{
    public function bootstrap(): void
    {
        parent::bootstrap();

        $this->addPlugin('Cake/Notification');
        $this->addPlugin('Cake/RocketChatNotification');
    }
}

Verify Installation

After installation, verify that the RocketChat channel is registered:

bash
bin/cake console
php
use Cake\Notification\NotificationManager;

$registry = NotificationManager::getRegistry();
$registry->dispatchDiscoveryEvent();

$channel = NotificationManager::channel('rocketchat');

Configuration

RocketChat Setup

1. Create Incoming Webhook

In your RocketChat instance:

  1. Go to AdministrationIntegrations
  2. Click New Integration
  3. Select Incoming WebHook
  4. Configure the webhook:
    • Name: Your application name
    • Post to Channel: Select default channel (can be overridden)
    • Post as: Bot username
    • Script Enabled: Yes (optional, for advanced processing)
  5. Save and copy the Webhook URL

The webhook URL will look like:

https://your-rocketchat.com/hooks/YOUR_HOOK_ID/YOUR_TOKEN

Basic Configuration

Add the webhook URL to your CakePHP configuration:

config/app_local.php (for local development):

php
<?php
return [
    'Notification' => [
        'channels' => [
            'rocketchat' => [
                'webhook' => 'https://your-rocketchat.com/hooks/YOUR_HOOK_ID/YOUR_TOKEN',
            ],
        ],
    ],
];

Using Environment Variables (recommended for production):

.env:

env
ROCKETCHAT_WEBHOOK_URL=https://your-rocketchat.com/hooks/YOUR_HOOK_ID/YOUR_TOKEN

config/app.php:

php
<?php
return [
    'Notification' => [
        'channels' => [
            'rocketchat' => [
                'webhook' => env('ROCKETCHAT_WEBHOOK_URL'),
                'timeout' => 30,
                'verify' => true,
            ],
        ],
    ],
];

Multiple RocketChat Instances

Configure multiple RocketChat workspaces or channels:

php
<?php
return [
    'Notification' => [
        'channels' => [
            'rocketchat' => [
                'webhook' => env('ROCKETCHAT_MAIN_WEBHOOK'),
            ],
            'rocketchat-alerts' => [
                'webhook' => env('ROCKETCHAT_ALERTS_WEBHOOK'),
            ],
            'rocketchat-support' => [
                'webhook' => env('ROCKETCHAT_SUPPORT_WEBHOOK'),
            ],
            'rocketchat-internal' => [
                'webhook' => env('ROCKETCHAT_INTERNAL_WEBHOOK'),
            ],
        ],
    ],
];

.env:

env
ROCKETCHAT_MAIN_WEBHOOK=https://main.rocketchat.com/hooks/XXX/YYY
ROCKETCHAT_ALERTS_WEBHOOK=https://main.rocketchat.com/hooks/AAA/BBB
ROCKETCHAT_SUPPORT_WEBHOOK=https://support.rocketchat.com/hooks/CCC/DDD
ROCKETCHAT_INTERNAL_WEBHOOK=https://main.rocketchat.com/hooks/EEE/FFF

Advanced Configuration

HTTP Client Options

Configure HTTP client options:

php
'rocketchat' => [
    'webhook' => env('ROCKETCHAT_WEBHOOK_URL'),
    'timeout' => 30,
    'connect_timeout' => 10,
    'verify' => true,
    'http_errors' => true,
],

Proxy Configuration

If you're behind a proxy:

php
'rocketchat' => [
    'webhook' => env('ROCKETCHAT_WEBHOOK_URL'),
    'proxy' => 'http://proxy.example.com:8080',
],

Custom Headers

Add custom headers to all requests:

php
'rocketchat' => [
    'webhook' => env('ROCKETCHAT_WEBHOOK_URL'),
    'headers' => [
        'X-Custom-Header' => 'value',
    ],
],

Routing Configuration

Entity-Level Routing

Configure routing on your entity:

php
<?php
namespace App\Model\Entity;

use Cake\ORM\Entity;

class User extends Entity
{
    public function routeNotificationForRocketchat(): ?string
    {
        return '#' . $this->team_channel;
    }
}

Table-Level Routing

Add behavior to your table:

php
<?php
namespace App\Model\Table;

use Cake\ORM\Table;

class UsersTable extends Table
{
    public function initialize(array $config): void
    {
        parent::initialize($config);
        $this->addBehavior('Cake/Notification.Notifiable');
    }
}

Testing Configuration

For testing, you can use a mock webhook URL:

config/app_local.php (development):

php
'rocketchat' => [
    'webhook' => 'https://webhook.site/your-unique-url',
],

Visit https://webhook.site to get a temporary webhook URL for testing.

Troubleshooting

Verify Configuration

php
use Cake\Core\Configure;

$config = Configure::read('Notification.channels.rocketchat');
debug($config);

Test Webhook Manually

bash
curl -X POST https://your-rocketchat.com/hooks/YOUR_HOOK_ID/YOUR_TOKEN \
  -H 'Content-Type: application/json' \
  -d '{"text":"Test message"}'

Usage

Creating Notifications

Basic Notification

Create a notification class:

php
<?php
namespace App\Notification;

use Cake\Datasource\EntityInterface;
use Cake\Notification\AnonymousNotifiable;
use Cake\Notification\Notification;
use Cake\RocketChatNotification\Message\RocketChatMessage;

class WelcomeNotification extends Notification
{
    public function via(EntityInterface|AnonymousNotifiable $notifiable): array
    {
        return ['database', 'rocketchat'];
    }

    public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): RocketChatMessage
    {
        return RocketChatMessage::create()
            ->text('Welcome to our platform!')
            ->emoji(':wave:');
    }
}

Sending Notifications

To a User Entity

php
$user = $this->Users->get($userId);
$user->notify(new WelcomeNotification());

To Multiple Users

php
$users = $this->Users->find('active');
foreach ($users as $user) {
    $user->notify(new WelcomeNotification());
}

use Cake\Notification\NotificationManager;

NotificationManager::send($users, new WelcomeNotification());

On-Demand Notifications

Send to a specific channel without a user entity:

php
use Cake\Notification\NotificationManager;

NotificationManager::route('rocketchat', '#general')
    ->notify(new SystemAlertNotification());

NotificationManager::route('rocketchat', '@john.doe')
    ->notify(new DirectMessageNotification());

Notification Examples

Simple Text Message

php
public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): RocketChatMessage
{
    return RocketChatMessage::create()
        ->text('Your order has been shipped!');
}

Message with Custom Username and Avatar

php
public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): RocketChatMessage
{
    return RocketChatMessage::create()
        ->text('Deployment successful!')
        ->username('Deploy Bot')
        ->avatar('https://example.com/bot-avatar.png')
        ->emoji(':rocket:');
}

Message with Attachments

php
public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): RocketChatMessage
{
    return RocketChatMessage::create()
        ->text('New deployment to production')
        ->attachment(function ($attachment) {
            $attachment->title('Version 2.1.0 Released')
                ->text('This release includes bug fixes and new features')
                ->color('good')
                ->field('Environment', 'Production', true)
                ->field('Version', 'v2.1.0', true)
                ->field('Deploy Time', '2 minutes', true)
                ->timestamp(time());
        });
}

Multiple Attachments

php
public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): RocketChatMessage
{
    return RocketChatMessage::create()
        ->text('Daily Status Report')
        ->attachment(function ($attachment) {
            $attachment->title('✅ Successful')
                ->text('All systems operational')
                ->color('good');
        })
        ->attachment(function ($attachment) {
            $attachment->title('⚠️ Warning')
                ->text('High CPU usage detected')
                ->color('warning');
        });
}

Rich Formatted Message

php
public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): RocketChatMessage
{
    return RocketChatMessage::create()
        ->text('New Order Received')
        ->username('Order Bot')
        ->emoji(':shopping_cart:')
        ->attachment(function ($attachment) {
            $attachment
                ->title("Order #{$this->orderId}", "https://app.example.com/orders/{$this->orderId}")
                ->text($this->orderSummary)
                ->color('#36a64f')
                ->field('Customer', $this->customerName, true)
                ->field('Total', '$' . number_format($this->total, 2), true)
                ->field('Items', $this->itemCount, true)
                ->field('Status', 'Pending', true)
                ->author(
                    $notifiable->name,
                    "https://app.example.com/users/{$notifiable->id}",
                    $notifiable->avatar_url
                )
                ->image('https://example.com/order-chart.png')
                ->timestamp(time());
        });
}

Using Different Channels

Single Channel

php
public function via(EntityInterface|AnonymousNotifiable $notifiable): array
{
    return ['rocketchat'];
}

Multiple Channels

php
public function via(EntityInterface|AnonymousNotifiable $notifiable): array
{
    return ['database', 'rocketchat', 'mail'];
}

Conditional Channels

php
public function via(EntityInterface|AnonymousNotifiable $notifiable): array
{
    $channels = ['database'];

    if ($notifiable->rocketchat_enabled) {
        $channels[] = 'rocketchat';
    }

    if ($this->priority === 'high') {
        $channels[] = 'rocketchat-alerts';
    }

    return $channels;
}

Named Channel Instances

php
public function via(EntityInterface|AnonymousNotifiable $notifiable): array
{
    return ['rocketchat-alerts', 'rocketchat-internal'];
}

Data Passing to Notifications

Constructor Parameters

php
class OrderShippedNotification extends Notification
{
    public function __construct(
        protected string $orderId,
        protected string $trackingNumber,
        protected string $carrier
    ) {}

    public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): RocketChatMessage
    {
        return RocketChatMessage::create()
            ->text("Order #{$this->orderId} shipped via {$this->carrier}")
            ->attachment(function ($attachment) {
                $attachment->field('Tracking', $this->trackingNumber);
            });
    }
}

$user->notify(new OrderShippedNotification('12345', 'TRACK123', 'UPS'));

Using Notifiable Data

php
public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): RocketChatMessage
{
    return RocketChatMessage::create()
        ->text("Hello {$notifiable->first_name}!")
        ->attachment(function ($attachment) use ($notifiable) {
            $attachment->field('Account Type', $notifiable->account_type)
                ->field('Member Since', $notifiable->created->format('Y-m-d'));
        });
}

Returning Different Message Types

php
public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): RocketChatMessage
{
    return RocketChatMessage::create()->text('Hello');
}

Array

php
public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): array
{
    return [
        'text' => 'Hello',
        'emoji' => ':wave:',
    ];
}

String

php
public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): string
{
    return 'Simple text message';
}

Null (Skip Sending)

php
public function toRocketChat(EntityInterface|AnonymousNotifiable $notifiable): mixed
{
    if (!$this->shouldNotify) {
        return null;
    }

    return RocketChatMessage::create()->text('Notification');
}

Message Builder API

RocketChatMessage

The RocketChatMessage class provides a fluent API for building rich RocketChat messages.

Creating a Message

php
use Cake\RocketChatNotification\Message\RocketChatMessage;

$message = RocketChatMessage::create();

Basic Properties

Text

Set the main message text:

php
$message->text('Hello, World!');

Username

Override the webhook's default username:

php
$message->username('Deploy Bot');

Avatar

Set a custom avatar URL:

php
$message->avatar('https://example.com/avatar.png');

Emoji

Set an emoji icon:

php
$message->emoji(':rocket:');

Complete Example

php
$message = RocketChatMessage::create()
    ->text('Deployment complete!')
    ->username('CI/CD Bot')
    ->avatar('https://example.com/bot.png')
    ->emoji(':white_check_mark:');

Attachments

Attachments allow you to add rich formatted content to messages.

Adding an Attachment

php
$message->attachment(function ($attachment) {
    $attachment->title('Deployment Details')
        ->text('Version 2.1.0 deployed successfully')
        ->color('good');
});

Multiple Attachments

php
$message
    ->text('Status Report')
    ->attachment(function ($attachment) {
        $attachment->title('Backend')->color('good');
    })
    ->attachment(function ($attachment) {
        $attachment->title('Frontend')->color('warning');
    });

Attachment from Array

php
$message->attachment([
    'title' => 'My Title',
    'text' => 'My Text',
    'color' => 'danger',
]);

RocketChatAttachment

Title

Set attachment title with optional link:

php
$attachment->title('Click Here', 'https://example.com');

Text

Set attachment body text:

php
$attachment->text('Detailed description here');

Color

Set the attachment color bar:

php
$attachment->color('good');
$attachment->color('warning');
$attachment->color('danger');
$attachment->color('#FF5733');

Fields

Add fields (displayed in a table):

php
$attachment->field('Environment', 'Production', true);
$attachment->field('Description', 'Long description text...', false);

Multiple fields example:

php
$attachment
    ->field('Status', 'Active', true)
    ->field('CPU', '45%', true)
    ->field('Memory', '2.5GB', true)
    ->field('Uptime', '15 days', true);

Images

Thumbnail

Small image on the right side:

php
$attachment->thumb('https://example.com/thumb.jpg');
Full Image

Large image at the bottom:

php
$attachment->image('https://example.com/chart.png');

Author Information

php
$attachment->author(
    'John Doe',
    'https://example.com/john',
    'https://example.com/avatar.jpg'
);

Timestamp

Unix timestamp for the attachment:

php
$attachment->timestamp(time());

Complete Examples

Server Status Report

php
RocketChatMessage::create()
    ->text('🖥️ Server Status Report')
    ->username('Monitoring Bot')
    ->emoji(':computer:')
    ->attachment(function ($attachment) {
        $attachment
            ->title('Production Server')
            ->text('All systems operational')
            ->color('good')
            ->field('CPU Usage', '23%', true)
            ->field('Memory', '4.2GB / 16GB', true)
            ->field('Disk Space', '45GB / 500GB', true)
            ->field('Uptime', '45 days', true)
            ->timestamp(time());
    })
    ->attachment(function ($attachment) {
        $attachment
            ->title('Database Server')
            ->text('Performance degraded')
            ->color('warning')
            ->field('Connections', '450 / 500', true)
            ->field('Query Time', '250ms avg', true)
            ->field('Replication Lag', '2.5s', true)
            ->timestamp(time());
    });

Deployment Notification

php
RocketChatMessage::create()
    ->text('🚀 New Deployment')
    ->username('Deploy Bot')
    ->emoji(':rocket:')
    ->attachment(function ($attachment) {
        $attachment
            ->title('Version 2.1.0 - Production', 'https://github.com/org/repo/releases/tag/v2.1.0')
            ->text('Successfully deployed with zero downtime')
            ->color('#36a64f')
            ->field('Environment', 'Production', true)
            ->field('Version', 'v2.1.0', true)
            ->field('Deploy Time', '2m 34s', true)
            ->field('Tests Passed', '1,247 / 1,247', true)
            ->author(
                'John Doe',
                'https://github.com/johndoe',
                'https://github.com/johndoe.png'
            )
            ->image('https://example.com/build-graph.png')
            ->timestamp(time());
    });

Error Alert

php
RocketChatMessage::create()
    ->text('🚨 Critical Error Detected')
    ->username('Alert Bot')
    ->emoji(':rotating_light:')
    ->attachment(function ($attachment) {
        $attachment
            ->title('Database Connection Failed')
            ->text('Unable to connect to primary database server')
            ->color('danger')
            ->field('Error Code', 'CONN_TIMEOUT', true)
            ->field('Server', 'db-prod-01', true)
            ->field('Time', date('Y-m-d H:i:s'), true)
            ->field('Impact', 'High - Service Degraded', false)
            ->timestamp(time());
    });

Order Notification

php
RocketChatMessage::create()
    ->text('🛒 New Order Received')
    ->emoji(':shopping_cart:')
    ->attachment(function ($attachment) use ($order) {
        $attachment
            ->title("Order #{$order->id}", "https://admin.example.com/orders/{$order->id}")
            ->text("{$order->item_count} items ordered")
            ->color('good')
            ->field('Customer', $order->customer_name, true)
            ->field('Total', '$' . number_format($order->total, 2), true)
            ->field('Payment', $order->payment_method, true)
            ->field('Shipping', $order->shipping_method, true)
            ->thumb($order->first_item_image_url)
            ->timestamp($order->created->timestamp);
    });

Build Status

php
RocketChatMessage::create()
    ->text('Build Status Update')
    ->username('CI Bot')
    ->attachment(function ($attachment) {
        $attachment
            ->title('Build #1234 - master', 'https://ci.example.com/builds/1234')
            ->text('Build completed with warnings')
            ->color('warning')
            ->field('Branch', 'master', true)
            ->field('Commit', 'abc1234', true)
            ->field('Duration', '5m 23s', true)
            ->field('Tests', '95 / 100 passed', true)
            ->field('Warnings', '3 code style issues', false)
            ->author(
                'Jane Smith',
                'https://github.com/janesmith',
                'https://github.com/janesmith.png'
            );
    });

Method Chaining

All methods return $this for fluent chaining:

php
$message = RocketChatMessage::create()
    ->text('Message')
    ->username('Bot')
    ->avatar('https://example.com/avatar.png')
    ->emoji(':robot:')
    ->attachment(function ($attachment) {
        $attachment
            ->title('Title')
            ->text('Text')
            ->color('good')
            ->field('Key', 'Value', true);
    });

Getters

Access message properties:

php
$message->getText();
$message->getUsername();
$message->getAvatar();
$message->getEmoji();
$message->getAttachments();

Array Conversion

Convert message to array for webhook:

php
$array = $message->toArray();

Output:

php
[
    'text' => 'Hello',
    'username' => 'Bot',
    'avatar' => 'https://example.com/avatar.png',
    'emoji' => ':wave:',
    'attachments' => [
        [
            'title' => 'Title',
            'text' => 'Text',
            'color' => 'good',
            'fields' => [
                ['title' => 'Field', 'value' => 'Value', 'short' => true],
            ],
        ],
    ],
]

Error Handling

php
use Cake\Notification\Exception\CouldNotSendNotification;

try {
    $user->notify(new WelcomeNotification());
} catch (CouldNotSendNotification $e) {
    $this->log("RocketChat notification failed: " . $e->getMessage());
    $channel = $e->getChannel();
    $response = $e->getResponse();
}

Testing

You may use the \Cake\Notification\TestSuite\NotificationTrait to prevent notifications from being sent during testing. Typically, sending notifications is unrelated to the code you are actually testing. Most likely, it is sufficient to simply assert that your application was instructed to send a given notification.

After adding the NotificationTrait to your test case, you may then assert that notifications were instructed to be sent and even inspect the message content:

php
<?php
namespace App\Test\TestCase;

use App\Notification\OrderShippedNotification;
use Cake\Notification\TestSuite\NotificationTrait;
use Cake\TestSuite\TestCase;

class OrderTest extends TestCase
{
    use NotificationTrait;

    protected array $fixtures = ['app.Users', 'app.Orders'];

    public function testOrderShippedNotification(): void
    {
        $usersTable = $this->getTableLocator()->get('Users');
        $user = $usersTable->get(1);

        $usersTable->notify($user, new OrderShippedNotification('12345', 'TRACK123'));

        $this->assertNotificationSentTo($user, OrderShippedNotification::class);
        $this->assertNotificationSentToChannel('rocketchat', OrderShippedNotification::class);
    }
}

Testing Message Format

You can test the message format by calling the channel method directly:

php
public function testRocketChatMessageFormat(): void
{
    $user = $this->getTableLocator()->get('Users')->get(1);
    $notification = new OrderShippedNotification('12345', 'TRACK123');

    $message = $notification->toRocketChat($user);

    $this->assertInstanceOf(RocketChatMessage::class, $message);
    $this->assertStringContainsString('Order #12345', $message->getText());
    $this->assertEquals(':package:', $message->getEmoji());
}

Updated at:

Released under the MIT License.