laravel/slack-notification-channel
Official Laravel notification channel for sending rich Slack messages via webhooks. Integrates with Laravel’s Notifications system, supports attachments/blocks, and works seamlessly with queues and notifiables for app alerts and updates.
Installation:
composer require laravel/slack-notification-channel
Publish the config file (if needed):
php artisan vendor:publish --provider="Laravel\SlackNotificationChannel\SlackServiceProvider"
Configure Slack:
Add your Slack webhook URL to .env:
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/...
First Notification:
Create a notification class extending SlackMessage:
use Laravel\SlackNotificationChannel\SlackMessage;
class DeploymentFailedNotification extends SlackMessage
{
public function __construct(public string $message)
{
$this->message = $message;
}
}
Send the Notification:
use App\Notifications\DeploymentFailedNotification;
use Illuminate\Support\Facades\Notification;
Notification::route('slack', '#general')
->notify(new DeploymentFailedNotification('Deployment failed!'));
config/services.php (for slack key)SlackWebhookChannel (handles delivery)Basic Text Messages:
Notification::route('slack', '#alerts')->notify(new SlackMessage('Hello, Slack!'));
Rich Attachments (Legacy):
class AlertNotification extends SlackMessage
{
public function toSlack($notifiable)
{
return [
'text' => 'Critical Alert!',
'attachments' => [
[
'title' => 'Error Details',
'text' => 'Check logs at: ' . url('/logs'),
'color' => '#ff0000',
],
],
];
}
}
BlockKit (Modern UI):
class InteractiveNotification extends SlackMessage
{
public function toSlack($notifiable)
{
return [
'blocks' => [
[
'type' => 'section',
'text' => [
'type' => 'mrkdwn',
'text' => 'Deploy *now*?',
],
],
[
'type' => 'actions',
'elements' => [
[
'type' => 'button',
'text' => 'Deploy',
'value' => 'deploy',
'action_id' => 'deploy_action',
],
],
],
],
];
}
}
Threaded Replies:
Notification::route('slack', '#general')
->notify(new SlackMessage('Initial message'))
->replyTo('thread_ts'); // Attach to existing thread
Conditional Logic:
class DynamicNotification extends SlackMessage
{
public function __construct(public bool $isCritical)
{
}
public function toSlack($notifiable)
{
return $this->isCritical
? ['text' => 'CRITICAL: System down!', 'blocks' => [...]]
: ['text' => 'Info: Maintenance scheduled'];
}
}
Notification::route('slack', '#logs')->notify(new SlackMessage('...'))->delay(now()->addMinutes(5));
Notification::route('slack', 'U12345678')->notify(new SlackMessage('DM for you!'));
event(new DeploymentEvent($repo));
// In listener:
Notification::route('slack', '#dev')->notify(new DeploymentNotification($event));
public function toSlack($notifiable)
{
return ['blocks' => json_decode(file_get_contents('path/to/blocks.json'), true)];
}
Empty Routes:
route() is empty.if (empty($route)) throw new \Exception('Slack route not configured');
BlockKit Validation:
Rate Limits:
$this->queueOn('slack_queue');
Attachment Limits:
Threading:
thread_ts must match an existing message timestamp.replyTo() with the original notification’s id.buildJsonPayload() to log raw output:
protected function buildJsonPayload($notifiable, $message)
{
\Log::debug('Slack Payload:', ['payload' => $message]);
return parent::buildJsonPayload($message);
}
ngrok http 8000
Configure .env:
SLACK_WEBHOOK_URL=https://your-ngrok-url.ngrok.io/slack
$channel = app('notifications')->createSlackChannel();
$channel->disableRouteValidation(); // Skip route checks
AppServiceProvider:
$this->app->bind(\GuzzleHttp\Client::class, function () {
return new \GuzzleHttp\Client(['timeout' => 10]);
});
Custom Slack Client:
Extend SlackWebhookChannel to add retries or logging:
class CustomSlackChannel extends \Laravel\SlackNotificationChannel\SlackWebhookChannel
{
public function send($notifiable, $message)
{
\Log::info('Sending Slack message', ['to' => $this->route]);
return parent::send($notifiable, $message);
}
}
Register in config/notifications.php:
'channels' => [
'slack' => [
'driver' => 'slack-custom',
],
],
Add Metadata: Attach custom fields to payloads:
class MetadataNotification extends SlackMessage
{
public function toSlack($notifiable)
{
return [
'text' => 'Notification with metadata',
'metadata' => ['user_id' => $notifiable->id, 'source' => 'api'],
];
}
}
Interactive Components: Handle Slack actions via a route:
Route::post('/slack/actions', function (Request $request) {
$payload = $request->json()->all();
if ($payload['actions'][0]['name'] === 'deploy_action') {
// Handle deployment
}
});
via() for Multi-Channel:
class MultiChannelNotification implements ShouldQueue
{
public function via($notifiable)
{
return ['mail', 'slack'];
}
}
$route = config('services.slack.route') ?? '#general';
Notification::route('slack', $route)->notify(...);
class TrackedSlackChannel extends SlackWebhookChannel
{
public function send($notifiable, $message)
{
try {
return parent::send($notifiable, $message);
} catch (\Exception $e) {
\DB::table('failed_jobs')->insert([...]);
throw $e;
}
}
}
How can I help you explore Laravel packages today?