skie / notification-slack
Slack notification channel for CakePHP Notification plugin
Installs: 1
Dependents: 0
Suggesters: 1
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:cakephp-plugin
pkg:composer/skie/notification-slack
Requires
- php: >=8.1
- skie/notification: @dev
Requires (Dev)
- cakephp/cakephp: ^5.0
- cakephp/cakephp-codesniffer: ^5.0
- phpunit/phpunit: ^10.1
This package is auto-updated.
Last update: 2025-10-19 19:31:56 UTC
README
Send notifications to Slack using both the modern Block Kit API and legacy attachments via webhooks using the CakePHP Notification plugin.
Features:
- ✅ Modern Block Kit API with rich interactive elements
- ✅ Legacy attachment API for backwards compatibility
- ✅ Fluent API for building messages
- ✅ Full type safety (PHPStan Level 8)
- ✅ Comprehensive test coverage
- ✅ CakePHP HTTP Client (no external dependencies)
Requirements
- PHP 8.1+
- CakePHP 5.0+
- CakePHP Notification Plugin
- Slack Incoming Webhook URL
Installation
composer require cakephp/notification-slack
Configuration
Two Channel Types
The plugin supports two Slack integration methods:
-
Incoming Webhooks (
SlackWebhookChannel
)- Simple webhook URLs
- No OAuth required
- One-way communication
- Perfect for notifications
-
Web API (
SlackWebApiChannel
)- Full Slack API access
- Requires OAuth bot token
- Two-way communication
- Advanced features (threads, metadata, etc.)
Setup for Webhooks
- Go to your Slack workspace
- Navigate to Apps → Manage Apps
- Search for "Incoming Webhooks"
- Click "Add Configuration"
- Select a channel and click "Add Incoming WebHooks Integration"
- Copy the Webhook URL
Setup for Web API
- Go to https://api.slack.com/apps
- Create or select your Slack App
- Navigate to "OAuth & Permissions"
- Add
chat:write
bot token scope - Install app to workspace
- Copy the "Bot User OAuth Token" (starts with
xoxb-
)
Load the Plugin
The plugin is loaded via config/plugins.php
:
'Cake/SlackNotification' => [],
Configure Channels
For Webhooks (config/app_local.php):
return [ 'Notification' => [ 'channels' => [ 'slack' => [ 'className' => 'Cake\SlackNotification\Channel\SlackWebhookChannel', 'webhook' => 'https://hooks.slack.com/services/YOUR/WEBHOOK/URL', ], ], ], ];
For Web API (config/app_local.php):
return [ 'Notification' => [ 'channels' => [ 'slack' => [ 'className' => 'Cake\SlackNotification\Channel\SlackWebApiChannel', 'bot_user_oauth_token' => 'xoxb-your-bot-token', 'channel' => '#general', // Default channel ], ], ], ];
Or use environment variables (.env):
# For Webhooks
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK/URL
# For Web API
SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_CHANNEL=#general
Usage
The plugin supports two message formats:
- Modern Block Kit - Rich interactive messages with blocks, buttons, and more
- Legacy Attachments - Backwards compatible attachment-based messages
Modern Block Kit API
Use the modern BlockKitMessage
for rich interactive messages:
<?php namespace App\Notification; use Cake\Datasource\EntityInterface; use Cake\Notification\AnonymousNotifiable; use Cake\Notification\Notification; use Cake\SlackNotification\BlockKit\BlockKitMessage; class OrderCompletedNotification extends Notification { public function __construct( protected string $orderNumber, protected float $total, ) {} public function via(EntityInterface|AnonymousNotifiable $notifiable): array { return ['database', 'slack']; } public function toSlack(EntityInterface|AnonymousNotifiable $notifiable): BlockKitMessage { return (new BlockKitMessage()) ->text("Order {$this->orderNumber} completed") ->headerBlock('🎉 New Order Completed!') ->dividerBlock() ->sectionBlock(function ($section) { $section->text("Order *{$this->orderNumber}* has been completed") ->markdown(); $section->field('Total')->markdown()->text("*$" . number_format($this->total, 2) . "*"); $section->field('Status')->text('✅ Completed'); }) ->actionsBlock(function ($actions) { $actions->button('View Order') ->url("https://example.com/orders/{$this->orderNumber}") ->primary(); $actions->button('Download Invoice') ->url("https://example.com/orders/{$this->orderNumber}/invoice"); }); } }
Block Kit Features
Header Block:
$message->headerBlock('Welcome to our Service!');
Section Block with Fields:
$message->sectionBlock(function ($section) { $section->text('Main section text')->markdown(); $section->field('Field 1')->text('Value 1'); $section->field('Field 2')->text('Value 2'); });
Actions Block with Buttons:
$message->actionsBlock(function ($actions) { $actions->button('Approve') ->value('approve_123') ->primary(); $actions->button('Reject') ->value('reject_123') ->danger() ->confirm('Are you sure?'); });
Context Block:
$message->contextBlock(function ($context) { $context->image('https://example.com/icon.png', 'Icon'); $context->text('Additional context information'); });
Image Block:
$message->imageBlock('https://example.com/chart.png') ->alt('Sales chart') ->title('Q4 Sales Performance');
Divider Block:
$message->dividerBlock();
Legacy Attachments API
Use the legacy SlackMessage
for attachment-based messages:
Creating a Notification
<?php namespace App\Notification; use Cake\Datasource\EntityInterface; use Cake\Notification\AnonymousNotifiable; use Cake\Notification\Notification; use Cake\SlackNotification\Message\SlackMessage; class DeploymentNotification extends Notification { public function __construct( protected string $version, protected string $environment ) {} public function via(EntityInterface|AnonymousNotifiable $notifiable): array { return ['database', 'slack']; } public function toSlack(EntityInterface|AnonymousNotifiable $notifiable): SlackMessage { return SlackMessage::create() ->from('Deploy Bot', ':rocket:') ->success() ->content("Deployment successful!") ->attachment(function ($attachment) { $attachment ->title('Version ' . $this->version) ->field('Environment', $this->environment, true) ->field('Time', date('Y-m-d H:i:s'), true) ->color('good'); }); } }
Sending Notifications
// To a user $user = $this->Users->get($userId); $user->notify(new DeploymentNotification('v2.1.0', 'production')); // On-demand to a webhook NotificationManager::route('slack', 'https://hooks.slack.com/services/...') ->notify(new DeploymentNotification('v2.1.0', 'production'));
Routing
Define routing on your entities:
class User extends Entity { public function routeNotificationForSlack(): ?string { return $this->slack_webhook_url ?? null; } }
Message Features
Basic Message
SlackMessage::create('Hello from CakePHP!');
Custom Username and Icon
SlackMessage::create() ->content('Deployment complete') ->from('Deploy Bot', ':rocket:');
Message Levels
SlackMessage::create() ->content('Success!') ->success(); // green color SlackMessage::create() ->content('Warning!') ->warning(); // yellow color SlackMessage::create() ->content('Error!') ->error(); // red/danger color
With Attachments
SlackMessage::create() ->content('New Order Received') ->attachment(function ($attachment) { $attachment ->title('Order #12345', 'https://example.com/orders/12345') ->content('Customer ordered 3 items') ->color('good') ->field('Total', '$99.99', true) ->field('Items', '3', true) ->image('https://example.com/order-preview.png') ->footer('Order System') ->timestamp(time()); });
Multiple Attachments
SlackMessage::create() ->content('Daily Report') ->attachment(function ($attachment) { $attachment->title('Sales')->field('Today', '$1,234'); }) ->attachment(function ($attachment) { $attachment->title('Orders')->field('Total', '45'); });
With Actions (Buttons)
SlackMessage::create() ->content('Approval Required') ->attachment(function ($attachment) { $attachment ->title('New User Registration') ->content('John Doe wants to join the team') ->action('Approve', 'https://example.com/approve/123', 'primary') ->action('Reject', 'https://example.com/reject/123', 'danger'); });
Advanced Options
SlackMessage::create() ->content('Notification with options') ->to('#general') // Override channel ->linkNames() // Link @mentions and #channels ->unfurlLinks(true) // Show link previews ->unfurlMedia(false); // Don't show media previews
Complete Example
public function toSlack(EntityInterface|AnonymousNotifiable $notifiable): SlackMessage { return SlackMessage::create() ->from('Orders Bot', ':shopping_cart:') ->success() ->content("New order from {$this->order->customer_name}") ->attachment(function ($attachment) { $attachment ->title("Order #{$this->order->id}", $this->order->url) ->field('Customer', $this->order->customer_name, true) ->field('Total', '$' . number_format($this->order->total, 2), true) ->field('Items', (string)$this->order->item_count, true) ->field('Status', $this->order->status, true) ->color('good') ->footer('Order System') ->footerIcon('https://example.com/icon.png') ->timestamp(time()) ->action('View Order', $this->order->url, 'primary') ->action('Contact Customer', $this->order->customer_url); }); }
Testing
composer test
composer cs-check
composer stan
License
MIT License. See LICENSE file.