laravel/slack-notification-channel
Official Laravel notification channel for sending messages to Slack. Integrates with the Notifications system to deliver alerts and updates via Slack, with support for rich message formatting. Includes tests, security policy, and MIT license.
Installation:
composer require laravel/slack-notification-channel
Publish the config file (if needed):
php artisan vendor:publish --provider="Laravel\SlackNotificationChannel\SlackServiceProvider"
Configure Slack Webhook:
Add your Slack webhook URL to .env:
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/XXX/YYY/ZZZ
First Notification:
Create a notification class extending SlackMessage:
use Laravel\SlackNotificationChannel\SlackMessage;
class OrderShipped extends SlackMessage
{
public function toSlack($notifiable)
{
return [
'text' => 'Order #'.$this->order->id.' has shipped!',
'blocks' => [
[
'type' => 'section',
'text' => [
'type' => 'mrkdwn',
'text' => '*Order Shipped* :rocket:'
]
]
]
];
}
}
Send Notification:
use App\Notifications\OrderShipped;
$user = User::find(1);
$user->notify(new OrderShipped($order));
#alerts channel.schedule.Basic Message Sending:
Use SlackMessage for simple text or block-based messages. Leverage Laravel’s Notification facade:
Notification::route('slack', $webhookUrl)->notify(new OrderShipped($order));
Rich Interactions:
public function toSlack($notifiable)
{
return [
'blocks' => [
['type' => 'section', 'text' => ['type' => 'mrkdwn', 'text' => 'Confirm action?']],
['type' => 'actions', 'elements' => [
['type' => 'button', 'text' => ['type' => 'plain_text', 'text' => 'Approve'], 'value' => 'approve'],
['type' => 'button', 'text' => ['type' => 'plain_text', 'text' => 'Reject'], 'value' => 'reject']
]]
]
];
}
return [
'attachments' => [
[
'title' => 'Order Details',
'fields' => [
['title' => 'ID', 'value' => $this->order->id, 'short' => true],
['title' => 'Status', 'value' => 'Shipped', 'short' => true]
]
]
]
];
Threaded Replies:
Reply to a specific Slack message using thread_ts:
public function toSlack($notifiable)
{
return [
'text' => 'Follow-up message',
'thread_ts' => '1234567890.000123' // Timestamp of parent message
];
}
Conditional Logic: Skip notifications based on conditions:
public function via($notifiable)
{
return $this->shouldSend() ? ['slack'] : [];
}
protected function shouldSend()
{
return config('app.env') === 'production';
}
Queue Notifications: Use Laravel queues to avoid blocking HTTP requests:
$user->routeNotificationFor('slack', $webhookUrl)->notify(new OrderShipped($order));
Configure queue in .env:
QUEUE_CONNECTION=database
Dynamic Webhook URLs: Store webhook URLs in the database and fetch them dynamically:
$notifiable->routeNotificationFor('slack', function ($notifiable) {
return $notifiable->slackWebhookUrl;
});
Testing:
Use SlackWebhookChannel with a mock webhook URL in tests:
$this->actingAs($user)
->notify(new OrderShipped($order))
->assertSentToSlack(function ($message) {
return $message['text'] === 'Order #123 shipped!';
});
Webhook URL Validation:
Block Kit Validation:
try {
$this->send($notifiable, $message);
} catch (\GuzzleHttp\Exception\RequestException $e) {
\Log::error('Slack notification failed:', ['response' => $e->getResponse()->getBody()]);
}
Rate Limiting:
Threading Issues:
thread_ts is invalid, Slack ignores the message. Always validate timestamps before sending.ts in your database and retrieve it when replying.Environment-Specific Config:
.env or database-driven configurations:
SLACK_WEBHOOK_URL=${APP_ENV === 'production' ? 'prod_url' : 'dev_url'}
Log Payloads:
Override buildJsonPayload to log the final payload:
public function buildJsonPayload($notifiable, array $message)
{
\Log::debug('Slack payload:', $message);
return parent::buildJsonPayload($notifiable, $message);
}
Slack API Responses: Inspect the raw response from Slack:
$response = $this->send($notifiable, $message);
\Log::debug('Slack response:', $response->getBody());
Block Kit Builder URL: Generate a URL to pre-fill the Block Kit Builder with your JSON:
$message = new SlackMessage();
$builderUrl = $message->getBlockKitBuilderUrl($payload);
// Open $builderUrl in your browser to validate blocks.
Custom Slack Clients:
Extend SlackWebhookChannel to use a custom HTTP client:
use Laravel\SlackNotificationChannel\SlackWebhookChannel;
use GuzzleHttp\Client;
class CustomSlackChannel extends SlackWebhookChannel
{
protected function sendThroughSlack($notifiable, array $message)
{
$client = new Client(['timeout' => 30]);
return $client->post($this->url, ['json' => $message]);
}
}
Dynamic Message Modification:
Override toSlack to modify messages based on the notifiable:
public function toSlack($notifiable)
{
$message = parent::toSlack($notifiable);
$message['text'] .= " (User: {$notifiable->name})";
return $message;
}
Slack Actions Handling: Use Slack’s Events API to handle interactive components (buttons, selects). Example:
// In your event listener for Slack actions
if ($payload['actions'][0]['name'] === 'approve') {
$this->handleApproval($payload['user']['id']);
}
Multi-Channel Notifications: Send to multiple Slack channels by routing:
$user->routeNotificationFor('slack', [
'alerts' => 'https://hooks.slack.com/alerts',
'general' => 'https://hooks.slack.com/general'
])->notify(new OrderShipped($order));
Then override toSlack to conditionally format messages per channel:
public function toSlack($notifiable,
How can I help you explore Laravel packages today?